JavaDependency Injection in Existing Java Code

Dependency Injection in Existing Java Code

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

The idea of dependency injection (DI), aka dependency Inversion, is the way we decouple dependency relationships between objects. It is more of a concept than a framework and is not bound by any language barrier. We generally encounter unwanted dependencies in the event of creating objects or during object interaction. This leads to a tight coupling. Dependency injection in Java initially may seem a circumlocution of control flow, yet with increasing lines of code the application becomes more maintainable. For the sake of good design, sacrificing efficiency is acceptable to some extent. And the goal to easy maintenance is where major software engineering tricks apply. This article tries to give a a hint of DI in a sample code scenario and analyze its applicability.

Dependency Injection in Java Applications

DI can be a necessary phenomenon, especially when designing a large application where we want to immunize existing code base to change with the slightest change in the service logic (business logic). DI separates business logic from object creation and allows us to select from among various implementation of dependency at run time through configuration files. This pattern is particularly useful for locating components or locating and instantiating software services. High cohesion of the individual modules and low coupling is an important trait of a good software design. DI can suitably implement this trait and leverage good software design principles. There are basically three ways to implement DI: constructor injection, setter injection, and interface injection. The choice of one can be arbitrary with each having its own pros and cons. Also one may use a combination of all three types. However, to maintain consistency and readability of the code, adhering to one type throughout the project is highly recommended.

Dependency Injection and Java Application Design

In our hypothetical payroll system, suppose we have three types of Employees: Salaried, Commissioned, and Hourly. The system should have a provision to add/remove other types of employee as well. Each type of employee has its own payment method, which is calculated according to some predefined norms. For example, an hourly employee’s payment is calculated according to the rate of pay per hour multiplied by the number of hours worked. So starting from scratch we have four classes as follows:

Design 1: Simple Design

Four classes
Four classes

Observe that the class PayrollApplication is tied to the three objects by the following code:

SalariedEmployee e1   = new   SalariedEmployee(); e1.payment();

CommissionedEmployee   e2 = new   CommissionedEmployee(); e2.payment()

HourlyEmployee e3 = new HourlyEmployee();   e3.payment()

The code in the PayrollApplication class above is completely tied with the different employee classes. If another type of employee object incorporated tomorrow, it has to be hard coded in the PayrollApplication class to reflect the changes. This may demand a major revamp of the existing code, which is not acceptable and definitely not a good design. To rectify the problem to some extent we can reduce this dependency with the help of polymorphism. The idea of implementing polymorphism here is to use an abstract class as the parent class in order to execute the methods of its child class. Then at runtime supply different children of the parent class. As a result the method of the child class gets executed instead. This idea gives the following class diagram.

Design 2: Using Polymorphism

Using Polymorphism
Using Polymorphism

Now the PayrollApplication class has the following code.

Employee e = new SalariedEmployee();

e.payment();

Employee e = new CommissionedEmployee();

e.payment();

Employee e = new HourlyEmployee();

e.payment();

This may seem alright but still the employee classes are tied with the above code. Also it is a case of partial polymorphism because object instantiations are hard coded in the application class. A better method would be to have a function where objects are injected in such a manner that the function is unaware or does not care what type of employee object is passed as an argument.

public void   createEmployee(Employee employee)

{

employee.payment();

}

Now the PayrollApplication class does not need to know the type of employee supplied to the function createEmployee(). We are almost there to achieve inversion of control and have apparently removed the dependency of the object in the PayrollApplication class. The Application class is independent of the type of employee object supplied and can call its own payment method according to the object supplied.

But the problem here is that somebody somewhere in the application has to inject the right object in the createEmployee() method. Somewhere the Employee object of SalariedEmployee or HourlyEmployee or CommissionedEmployee is created such as: Employee emp = new SalariedEmployee() and then only the object is supplied as an argument to createEmployee(emp). Thus we are still tied and somehow not dependency free. To solve this problem comes the notion of a container that can supply objects that we require without bothering about its instantiation, destruction and its life cycle management. That’s hard work developing such a container every time when working on a project. Fortunately, there are a number of frameworks available to make your life easier. Some of these frameworks, though not limited to these, are:

  • Spring: It is a large framework that offers more than just dependency injection (DI)
  • PicoContainer: Small framework particularly focused on dependency injection
  • Xwork: a command pattern framework but also effectively leverages Dependency Injection. It is generally used in association with Webwork
  • Guice: It is a lightweight framework improvised to use annotation to configure Java objects.
  • Autumnframework: This dependency injection framework for C++ supports constructor and setter injection of POCO (Plain old C++ objects) objects.

Here we shall focus on the Spring framework for our design and use a very simple coding pattern that can get this application up and running.

Container for the Contain

Spring is basically a container of beans in much the same way Tomcat is the container of servlets. Tomcat creates the servlet objects, which are required to run. While deploying what we do is to configure all the servlet in an XML file. Tomcat reads the XML and identifies what servlets need to be instantiated and creates those servlets. Spring is also a container not of servlets but of beans; pretty much any POJO can be contained in the container. All these are managed by the spring and handles complete responsibility of instantiation of object, life cycle of the object and destruction of the objects.

The interaction of the object with Spring container can be depicted as:

 Spring Framework
 Spring Framework

Putting it Together in Spring

Employee.java

Abstract class incorporating the basic properties of the employee. Sub-classes extending this must define the payment() method according to the rules applicable as per the type of employee. The reason for declaring the payment() method as an abstract is – it simply does not make sense to provide an implementation of this method in this class. We cannot calculate the earnings for a general employee – we first must know the specific Employee type to determine appropriate payment calculation.

package org.payroll;

publicabstractclass Employee {

private String firstName;

private String lastName;

private String ssn;

public Employee(){

}

//Getter and Setter   methods

...

publicabstractdouble payment();

}

SalariedEmployee.java

This class is a subclass of Employee and defines the abstract payment() method of its parent class. It assumes the payment is weekly/monthly.

package org.payroll;

publicclass SalariedEmployee extends Employee {

privatedoublesalary;

public SalariedEmployee(){ 

}

@Override

publicdouble payment() {

return getSalary();

}

//Getter and Setter   methods

... 

}

HourlyEmployee.java

This class is a subclass of Employee and defines the abstract payment() method of its parent class. Here the payment method also calculates overtime jobs and adds the extra earnings to the final payment.

package org.payroll;

publicclass HourlyEmployee extends Employee {

privatedoublewage;

privatedoublehours;

@Override

publicdouble payment() {

if (this.getHours()   

returnthis.getWage() * this.getHours();

else

return 40 * this.getWage() + (this.getHours() - 40)

* this.getWage() * 1.5;

}

//Getter and Setter   methods

...

}

CommissionEmployee.java

This class retrieves the commission rate and gross sales respectively and calculates its payment accordingly.

package   org.payroll;

publicclass CommissionEmployee extends Employee {

privatedoublegrossSales;

privatedoublecommissionRate;

public CommissionEmployee() {

}

@Override

publicdouble payment() {

returnthis.getCommissionRate() * this.getGrossSales();

}

//Getter and Setter   methods

...

}

PayrollMain.java

This is the main application class, which acts as an interface to retrieve/view employee information. This is the class where we can see the actual role of Spring DI. Spring container gets the necessary configuration information through ApplicationContext context = new ClassPathXmlApplicationContext(“spring.xml”);

So whenever context.getBean()method is called Spring container supplies a reference of the appropriate bean instantiated within the container.

package   org.payroll;

import java.util.ArrayList;

import java.util.List;

import org.springframework.context.ApplicationContext;

import   org.springframework.context.support.ClassPathXmlApplicationContext;

publicclass PayrollMain{

publicstaticvoid main(String args[]) {

List employees = new ArrayList<>();

ApplicationContext   context = new   ClassPathXmlApplicationContext("spring.xml");

SalariedEmployee se   = context.getBean(SalariedEmployee.class);

se.setFirstName("Thor");

se.setLastName("Odinson");

se.setSsn("123-234-45");

se.setSalary(2000.00);

CommissionEmployee   ce = context.getBean(CommissionEmployee.class);

ce.setFirstName("Jacques");

ce.setLastName("Duquesne");

ce.setSsn("345-67-890");

ce.setGrossSales(345);

ce.setCommissionRate(0.56);

HourlyEmployee he =   context.getBean(HourlyEmployee.class);

he.setFirstName("Bruce");

he.setLastName("Banner");

he.setSsn("567-78-678");

he.setHours(30);

he.setWage(500);

employees.add(se);

employees.add(ce);

employees.add(he);

for(Employee e: employees){

System.out.printf("nName: %s %s   Payment: %.2f",e.getFirstName(), e.getLastName(), e.payment());

}

}

}

spring.xml

This configuration file is supplied to the ApplicationContext to acknowledge Spring container about the beans. Each bean is declared within the tag … where id is the name given to the bean, which we could have used as…

HourlyEmployee he = context.getBean("hourlyEmployee");

instead of…

HourlyEmployee he = context.getBean(HourlyEmployee.class);

Bean Scopes: Singleton Vs Prototype

There are basically two types of bean scopes in Spring: Singleton and Prototype. Singleton is partially analogous to the singleton pattern in Java. Here once we initialize an ApplicationContext and pass to it the configuration file (spring.xml), it instantiates all the beans in the XML, one bean per bean definition. As it creates only one bean per spring container no matter how many calls are made to the getBean() method, the spring container returns only that particular instance. Here lies the difference between the singleton pattern in Java and Spring scoped singleton. Singleton pattern in Java ensures that there is only one instance overall but singleton in Spring refers one instance per spring container where a single JVM can run multiple such containers. Scope prototype on the other hand overrides the default behavior of ApplicationContext and does not instantiate beans until the getBean() method is called. Each call to getBean() method instantiates a new bean.

Since there can be more than one employee per employee type, beans are scoped as prototype.

xmlversion="1.0"encoding="UTF-8"?>

DOCTYPE beans PUBLIC   "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>

<bean id="employee" abstract="true" scope="prototype">

bean>

<bean id="salariedEmployee"   class="org.payroll.SalariedEmployee"   scope="prototype">

bean>

<bean id="hourlyEmployee"   class="org.payroll.HourlyEmployee"   scope="prototype">

bean>

<bean id="commissionEmployee"   class="org.payroll.CommissionEmployee"   scope="prototype">

bean>

beans>

Conclusion

The concept of DI decouples objects dependency to a whole new level. Martin Fowler has a good article with some excellent insight on dependency injection. There are several ways to implement DI java. The choice of a particular technique is immaterial. DI leverages building pluggable service software that lives up to the Open-Closed principle. Building large enterprise applications with numerous fine grained services can benefit equally with DI implementation.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories