How I explained Dependency Injection to My Team

Recently our company started developing a new java based web application and after some evaluation process we decided to use Spring.

But many of the team members are not aware of Spring and Dependency Injection principles.
So I was asked to give a crash course on what is Dependency Injection and basics on Spring.

Instead of telling all the theory about IOC/DI I thought of explaining with an example.

Requirement: We will get some Customer Address and we need to validate the address.
After some evaluation we thought of using Google Address Validation Service.

 Legacy(Bad) Approach:

Just create an AddressVerificationService class and implement the logic.

Assume GoogleAddressVerificationService is a service provided by Google which takes Address as a String and Return longitude/latitude.

class AddressVerificationService 
{
public String validateAddress(String address)
{
GoogleAddressVerificationService gavs = new GoogleAddressVerificationService();
String result = gavs.validateAddress(address);
return result;
}
}

Issues with this approach: 
 1. If you want to change your Address Verification Service Provider you need to change the logic.
 2. You can’t Unit Test with some Dummy AddressVerificationService (Using Mock Objects)

 Due to some reason Client ask us to support multiple AddressVerificationService Providers and we need to determine which service to use at runtime.

To accomidate this you may thought of changing the above class as below:

class AddressVerificationService
{
//This method validates the given address and return longitude/latitude details.
public String validateAddress(String address)
{
String result = null;
int serviceCode = 2; // read this code value from a config file
if(serviceCode == 1)
{
GoogleAddressVerificationService googleAVS = new GoogleAddressVerificationService();
result = googleAVS.validateAddress(address);
} else if(serviceCode == 2)
{
YahooAddressVerificationService yahooAVS = new YahooAddressVerificationService();
result = yahooAVS.validateAddress(address);
}
return result;
}
}

Issues with this approach: 


1. Whenever you need to support a new Service Provider you need to add/change logic using if-else-if.
 2. You can’t Unit Test with some Dummy AddressVerificationService (Using Mock Objects)

 IOC/DI Approach: 

 In the above approaches AddressVerificationService is taking the control of creating its dependencies.
 So whenever there is a change in its dependencies the AddressVerificationService will change.

 Now let us rewrite the AddressVerificationService using IOC/DI pattern.

 class AddressVerificationService
{
private AddressVerificationServiceProvider serviceProvider;

public AddressVerificationService(AddressVerificationServiceProvider serviceProvider) {
this.serviceProvider = serviceProvider;
}

public String validateAddress(String address)
{
return this.serviceProvider.validateAddress(address);
}
}

interface AddressVerificationServiceProvider
{
public String validateAddress(String address);
}

Here we are injecting the AddressVerificationService dependency AddressVerificationServiceProvider.

Now let us implement the AddressVerificationServiceProvider with multiple provider services.

 class YahooAVS implements AddressVerificationServiceProvider
{
@Override
public String validateAddress(String address) {
System.out.println("Verifying address using YAHOO AddressVerificationService");
return yahooAVSAPI.validate(address);
}
}

class GoogleAVS implements AddressVerificationServiceProvider
{
@Override
public String validateAddress(String address) {
System.out.println("Verifying address using Google AddressVerificationService");
return googleAVSAPI.validate(address);
}
}

Now the Client can choose which Service Provider’s service to use as follows:

 AddressVerificationService verificationService = null;
AddressVerificationServiceProvider provider = null;
provider = new YahooAVS();//to use YAHOO AVS
provider = new GoogleAVS();//to use Google AVS

verificationService = new AddressVerificationService(provider);
String lnl = verificationService.validateAddress("HitechCity, Hyderabad");
System.out.println(lnl);

For Unit Testing we can implement a Mock AddressVerificationServiceProvider.

 class MockAVS implements AddressVerificationServiceProvider
{
@Override
public String validateAddress(String address) {
System.out.println("Verifying address using MOCK AddressVerificationService");
return "<response><longitude>123</longitude><latitude>4567</latitude>";
}
}

AddressVerificationServiceProvider provider = null;
provider = new MockAVS();//to use MOCK AVS
AddressVerificationServiceIOC verificationService = new AddressVerificationServiceIOC(provider);
String lnl = verificationService.validateAddress("Somajiguda, Hyderabad");
System.out.println(lnl);

With this approach we elemenated the issues with above Non-IOC/DI based approaches.
 1. We can provide support for as many Provides as we wish. Just implement AddressVerificationServiceProvider and inject it.
 2. We can unit test using Dummy Data using Mock Implementation.

So by following Dependency Injection principle we can create interface-based loosely-coupled and easily testable services.

Java Best Practices : Building Safe Domain Objects

Domain objects are the core building blocks of any application. These are the fine grained objects which carries the information about the problem domain model.
Generally domain objects will be created as dumb data carriers with setters/geters without having any logic. But this will cause huge problem in long run.
If you build the domain objects with dumb setters and getters we will end up in writing null checks all over the places.

I bet many of us have seen the code snippets like:

User user = ....;
if(user!=null)
{
String email = user.getEmail();
if(email != null && StringUtils.trimToNull(email) != null)
{
emailService.sendEmail(....);
}
else
{
throw new Exception("Email should not be null/blank");
}

}

Here email address of User object should not be null at all(It could be a not null property in database).

But with dumb domain objects with only setters/getters we will end up writing code to check for nulls as mentioned above.

We can get rid of this null checks in all over the places we can use Builder pattern.

Assume we need to write a domain Object User with properties id, firstname, lastname, email, dob, phone.
Among them id, firstname, lastname, email properties are mandatory and should not be null or blank.

In this case we can write the User class using Builder pattern as follows:

package com.sivalabs.core.model;

import java.util.Date;

/**
* @author Siva
*
*/
public class User
{
private Integer id;
private String firstname;
private String lastname;
private String email;
private Date dob;
private String phone;

private User()
{
}

private User(Integer id, String firstname, String lastname, String email)
{
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
this.email = email;
}

public static final User build(Integer id, String firstname, String lastname, String email)
{
if(id == null || id < 0){
throw new IllegalArgumentException("Id should not be null or negetive.");
}
if(firstname == null || firstname.trim().length()==0){
throw new IllegalArgumentException("firstname should not be null or blank.");
}
if(lastname == null || lastname.trim().length()==0){
throw new IllegalArgumentException("lastname should not be null or blank.");
}
if(email == null || email.trim().length()==0){
throw new IllegalArgumentException("email should not be null or blank.");
}
if(!email.contains("@")){
throw new IllegalArgumentException("Invalid email address.");
}
return new User(id,firstname, lastname, email);
}

public Integer getId() {
return id;
}
public String getFirstname() {
return firstname;
}

public String getLastname() {
return lastname;
}

public String getEmail() {
return email;
}

public Date getDob() {
return new Date(dob.getTime());
}

public User dob(Date dob) {
this.dob = new Date(dob.getTime());
return this;
}
public String getPhone() {
return phone;
}
public User phone(String phone) {
this.phone = phone;
return this;
}

}

Following are the steps to build safe domain objects:

1. Make default constructor as private preventing others creating empty instances.  
2. Create a private parametrized constructor with mandatory arguments only.  
3. Provide a public static build() method taking mandatory arguments, validate them and then build the object using parametrized constructor.  
4. Create setter methods (I have used Method chaining here) for optional properties. 
 
With this procedure I need not check for nulls for the mandatory arguments becuase if I have a non-null user object means it contains valid values for mandatory properties.

What is Inversion Of Control (IOC)?

Inversion Of Control is a design pattern which suggests the creation of collaborating objects and injecting them should not be done by the dependent object itself.

For example, Suppose WhetherController(Servlet) is depend on WhetherService which is depend WhetherDAO.

WhetherController .java
class WhetherController extends HttpServlet
{
protected doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
{
WhetherService service = new WhetherService();
service.doSomething(params);
….
….
}
}

WhetherService.java
class WhetherService
{
public void doSomething(Map params)
{
WhetherDAO dao = new WhetherDAO();
dao.getWhetherReport();
}
}

WhetherDAO.java
class WhetherDAO
{
// code to interact with Database
}

If you code as said above and if it is a big project you may use WhetherService/WhetherDAO in several classes. Later on, Suppose due to some reasons you need to change the WhetherService/WhetherDAO class as follows.

WhetherService.java
class WhetherService
{
private WhetherService whetherService = new WhetherService();
private WhetherService(){ }
public WhetherService getWhetherService()
{
return whetherService;
}
}

WhetherDAO.java
class WhetherDAO
{
private JDBCConnection connection = null;
public WhetherDAO(JDBCConnection connection)
{
this.connection = connection;
}
// code to interact with Database
}

Then as you are already using WhetherService/WhetherDAO classes in several places you need to make changes in several classes, which is cumbersome task.

The mail flaw in this design is WhetherController servlet is taking the responsibilty of creating WhetherService instances and WhetherService class is taking the responsibilty of creating WhetherDAO objects. Thereby your classes are tightly coupled.

To get rid of this problem, The IOC(Inversion Of Control) Design patetern suggests that have a Container which is responsible for creation of objects and their dependent objects and injecting them and serve them. When the client requested an object from the container, the container will give full fledzed objects with all dependencies set.

Let us see how we can change the above design by following IOC design pattern.

WhetherController .java

class WhetherController extends HttpServlet
{
private WhetherService whetherService;
public void setWhetherService(WhetherService whetherService)
{
this.whetherService = whetherService;
}

protected doPost(HttpServletRequest req, HttpServletResponse res) throws IOException,ServletException
{
this.whetherService.doSomething(params);
….
….
}
}

WhetherService.java
class WhetherService
{
private WhetherDAO whetherDAO ;
public void setWhetherDAO(WhetherDAO whetherDAO)
{
this.whetherDAO =whetherDAO;
}

public void doSomething(Map params)
{
this.whetherDAO.getWhetherReport();
}
}

WhetherDAO.java
class WhetherDAO
{
private JDBCConnection connection = null;
public WhetherDAO(JDBCConnection connection)
{
this.connection = connection;
}
// code to interact with Database
}

Container.java

public class Container
{
private static Map objectMap = new HashMap();
static

{
JDBCConnection connection = new JDBCConnection();
objectMap.put(”connection”,connection);

WhetherDAO whetherDAO = new WhetherDAO(connection);
objectMap.put(”whetherDAO”,whetherDAO);

WhetherService whetherService = new WhetherService();
whetherService.setWhetherDAO(whetherDAO);
objectMap.put(”whetherService”,whetherService);

}

public static Object getObject(String objectId)
{
Object obj = objectMap.get(objectId);
if(obj==null)
{
throw new RuntimeException(”Invalid objectId is given”);
} return obj;
}
}

Now the WhetherController servlet can be changed as follows:

WhetherController .java

class WhetherController extends HttpServlet
{
private WhetherService whetherService;

public WhetherController()
{
WhetherService whetherService =(WhetherService)
Container.getObject(”whetherService”);
setWhetherService(whetherService);
}

public void setWhetherService(WhetherService whetherService)
{
this.whetherService = whetherService;
}

protected doPost(HttpServletRequest req, HttpServletResponse res) throws IOException,ServletException
{
this.whetherService.doSomething(params);
….
….
}
}

Now if you need to change the way of object creation the only place we need to modify Container class only.

Today there are several IOC container are available implemented using Java such as Spring, Pico etc.Among them Spring becomes very much popular as it is not only the IOC container.

Spring became an Application Framework which provides several features in all the layers such as web/service/dao layers. Unlike the other frameworks like Struts/Hibernate, Spring is not limited to only Web/Persistence layers. And one more great feature of Spring is pluggability with other frameworks.

Spring can be used with several other pupular frameworks like Struts1.x, Struts2,JSF, WebWork,IBatis,Hibernate, EJB etc.

For more information on Spring,visit http://static.springframework.org/spring/docs/2.5.x/reference/index.html