I had mentioned about Inversion of Control (IoC) in my earlier post Inversion of Control – for easy integration. In this post I will show you how you can actually make your integration easy with implementation of a mini application sample based on IoC.

Objective
The main objective of this mini tutorial is to highlight the implementation of an interface based Inversion of Control (IoC) architecture and to state how it could help in the integration and maintenance of the application.

For this mini application I will use the following set of classes

  1. Dependency – This is the interface which is implementation as per my application versions progress and which will be used by the View components in my application. In other words this is my Model component in a MVC architecture
  2. Dependent – This is my View component which uses the Model component to produce the results for displaying. As the name suggests the class is dependent on the Dependency implementation.
  3. Injector – This is most important class in the application and which introduces the aspect of Inversion Of Control into the applications. This class can also be referred as the configurator class.
  4. Finally there can a number of implementations of the Dependency interface according to the needs of the application.

Note: This mini tutorial is based on the concept of Interface based IOC. It also assumes that you import the required classed in your Classes when compiling them.

Lets start with our tutorial.

Dependency.java

public interface Dependency {
	public void doSomething();
}

Dependency is the generic interface which my application supports. The IoC is done by a configurater class which will inject the dependency of the implementation object based on the runtime requirements and then provide it to my application. Hence my application can support various types and versions of the implementations until and unless they follow the contract as per the Dependency interface. Sometimes this technique is referred to as “Design By Contract“. So for any interface based IoC design, your set of interfaces in the application must be finalized since they prove as the reference to be used inside the configurater classes.

DependencyImplOne.java

public class DependencyImplOne implements Dependency{
 
	public void doSomething() {
		System.out.println("Hello World! This is the first implementation for Dependency");
	}
 
}

This is my first implementation for the Dependency interface. It just implements the single method doSomething() and displays some text.

ioc.properties

# You can have your own package instead of the one mentioned here.
package.name = com.techtracer.ioc
class.name = DependencyImplOne

This is a simple external IoC configuration file . It defines the values for the package name and the implementation class name. I have used an external file in order to highlight the benefits of not having to hard-code the required parameters in the program.

Injector.java

public class Injector {
	public static Dependency getInstance(String propertiesFile){
		Dependency d = null;	
 
		Properties p = new Properties();
 
		try {
			p.load(new FileInputStream(propertiesFile));
		} catch (Exception e) {
			System.out.println("Could not load file");
		}
 
		String packageName = p.getProperty("package.name");
		String className = p.getProperty("class.name");
		String impl = packageName + "." + className;		
 
		try {
			System.out.println("Instantiating Type : "+  impl);
			d = (Dependency) Class.forName(impl).newInstance();
		} catch (Throwable e) {
			/*
			 * You have to remember to catch a Throwable here
			 * since only catching an Exception could still throw an
			 * NoClassDefFoundError if you supply a wrong class name
			 */
			d = null;
		}
 
		return d;
	}
}

Finally this is actual class on which my IoC architecture will depend. This is the configurator class which will inject the Dependency implemented object based on the application requirements in runtime. However I am free to change this class anytime I want and provide a new dependency to my application either through hard-coding or through some configuration properties or XML file. It is like a pre processor which acts between the object creation and the object consuming phase and is the heart of the IoC architecture.

You might see that I have used Reflection for getting the class name to be instantiated as shown in the syntax Class.forName(). You are not expected to know this and you can very well use a different type of instantiation method of your choice or simply create an new DependencyImplOne() and return it. Also for this tutorial I have used the above created ioc.properties file. Remember this file has to be stored in your application ROOT folder and not the package directories.

Running the application
Now after creating all the classes you are ready to run the first IoC implementation. Just compile the set of classes in your package and after running the Dependent.java class you should be able to see the output:

Instantiating Type : com.techtracer.ioc.DependencyImplOne
Hello World! This is the first implementation for Dependency

Congratulations! if you were successfully able to run the program.

IoC for easier integration
Now suppose at a later point of time you would like to change the behavior of your program and it should be able to produce another output instead of what the DependencyImplOne.java provides. But what if you have to do this without ever having to touch the source code of your earlier code. Is this possible?

The answer to the question is YES. This is because due to the IoC provided by the Injector class now you have the full flexibility in modifying the runtime behavior of your application by just creating another class which implements the Dependency interface and mention the newly created and compiled class inside your ioc.properties file.

So I would now create another class with the name DependencyImplTwo.java and simply put a different output String in place of the original.

public class DependencyImplTwo implements Dependency{
	public void doSomething() {
		System.out.println("This is the second implementation for Dependency");
	}
}

Remember this class has to import the Dependency interface but it itself can be placed in any package regardless of the package structure of the original source code. After compiling the above class you should once again run the Dependent.java class as earlier and check the output. The output now should be:

Instantiating Type : com.techtracer.ioc.DependencyImplTwo
This is the second implementation for Dependency

Conclusion
So, with this tutorial it is clear that with the help of an IoC architecture you can change the dependencies as and when required without affecting the rest of the components in your application, thus avoiding side effects of the frequent changes done to it. It’s also very easy to maintain and involves just placing the classes in their proper location.

Thus your application can be scaled and adapted to a changing environment by reducing the number of dependencies an application can encounter during its lifespan. However you have to be careful in designing the architecture and choose properly which are your Dependent components and which are your Dependencies since the interfaces are used to map the dependencies with those required for the dependents.


Stumble Digg Technorati Subscribe Delicious