Unless you have been living under a rock, you must have heard about dependency injection and IOC (Inversion of Control) containers. In this post we would analyse what is dependency injection and why is it even important. We would be using example from our shopping cart series, so if you have not been paying attention, please checkout part 1 and part 2 of the series.

If we look at our servlet from JDBC post, we see that we had to create a new instance of our DAO before using it.

WineDao dao = new WineDao();
List listOfWines = dao.getListOfWines();

This makes WineDao a dependency to our Servlet, in other words our Servlet is dependent on WineDao to fetch the wine details from what ever storage system we are using. This makes our Servlet agnostic of all the database internals, aka if we were to switch from in memory database to nosql database or a webservice the code in Servlet would not change. Seems like a good thing right?

However, there is a teeny little problem, we are dependent on the WineDao class and implementation, so if we were to replace WineDao with WineService which gets wine information from a web service or an external site, we can not do it. We are kind of stuck with classname and implementation, this is known as tight coupling, that is because you would have heard the opposite loose coupling many times. So lets start with tightly coupled example and improvise it till we get our near perfect solution. Hey! I told you that we will learn it the hard way, thats the only way to learn it right.

So now if we want to remove the dependency of WineDao class, we can extract an interface called WineDependency. I know its a very unimaginative name, but I am intentionally avoiding calling it a service or dao or repository, lets just keep it simple and call it WineDependency.

public interface WineDependency {

	public List getListOfWines();
}

Now as long as we have any class implementing this interface, we should be good, it may be WineDao or WineService right? So our Servlet would change to following.

WineDependency dependency = new WineDao();
List listOfWines = dependency.getListOfWines();

That doesnt sound right , we still have to import WineDao which would defeat the purpose of creating interface right. So we need to move the creation part of WineDao out of Servlet. So lets create a WineDependencyFactory which would create a new WineDao and supply it to our Servlet.

WineDependency dependency = WineDependencyFactory.getDependency();
public class WineDependencyFactory {

	public static WineDependency getDependency(){
		return new WineDao();
	}
}

Now our servlet is not dependent on WineDao but on a factory, this solution works nice but we would need to create a factory for each and every dependency. We could create a single factory which would have all the dependency and we could ask the single factory to give the necessary dependency. This pattern is called ServiceRegistry, the most common example is JNDI, where all the services are registered and you look up the service using a jndi name.

How about if we could dynamically create instances of each of the dependency and keep it in the service registry, then our solution would scale to any number of dependency without changing the ServiceRegistry code, lets see.

public class WineServiceRegistry {

	private List<String> dependencyClasses = new ArrayList<>();

	private List<Object> dependencies = new ArrayList<>();

	public void scanAllDependencies() {
		dependencyClasses.add("com.learnithardway.web.WineDao");
	}

	public void initializeDependency() {
		scanAllDependencies();
		for (int i = 0; i < dependencyClasses.size(); i++) {
			try {
				String clazzName = dependencyClasses.get(i);
				Object instance = Class.forName(clazzName).newInstance();
				dependencies.add(instance);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public Object getWineDependency(Class clazzname) {
		for (Object object : dependencies) {
			if (clazzname.isAssignableFrom(object.getClass()))
				return object;
		}
		return null;
	}
}

public class IndexServlet extends HttpServlet {
	WineDependency dependency = null;
	WineServiceRegistry registry = new WineServiceRegistry();

	public IndexServlet() {
		registry.initializeDependency();
		dependency = (WineDependency) registry.getWineDependency(WineDependency.class);
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		List<String> wines = new ArrayList<>();
		List<WineDetail> listOfWines = dependency.getListOfWines();
		request.setAttribute("wines", listOfWines);
		request.getRequestDispatcher("wines.jsp").forward(request, response);
	}

}

This looks about right, lets make a simple but crucial twist to the code, instead of servlet calling to get dependency, we could inject the dependency into servlet, this is called Hollywood Principle, Dont call us, we will call you. By making this twist, we have inverted the control of dependency from caller to registry aka container. Now the container could be in any form, the simplest example would be to manually create all dependency and inject them in each other, or we could use fancy xml or annotation. Either ways we would have created a very rudimentary IOC (Inversion Of Control) container.

The full source for this article is available at https://github.com/nitizkumar/shopping-cart-ioc-container, feel free to check it out.


Author

Nitiz

There are currently no comments.

Bitnami