Tuesday, February 6, 2007

A pluggable IoC mechanism for webwork application.

I am working as a software engineer in a middle size software firm called Cash-Tech. We are mainly into Cash Management systems. Our main development is done in java, J2EE applications. These applications have really evolved within last 3-4 years (as I have worked on a project which is almost 4 years old now and also on a project which is only a few months old now). Our technology head, Mr. Dananjay Nene, is an inspiring individual who leads the development with exquisite use of new technologies in the applications. His vision and ability has helped the company to become one of the leading companies in Cash Management.

Recently I came across one of his articles, A beginners guide to Dependency Injection. Dependency Injection is one of the interesting new design patterns mainly for web based applications. The moral of this pattern is injecting a required resource on demand rather creating the resource upfront. Inversion of control (IoC) is another idiom used for this design pattern. Some of the DI/IoC containers are ...

Spring framework PicoContainerHiveMind
XWork

XWork used in conjunction with WebWork has an inbuilt mechanism for IoC. But I decided to implement IoC mechanism for Webwork applications of my own. In an action class, sometimes we need some resources in the execute() method. These resources can be injected by a DI container. I wanted to build a DI/IoC mechanism which will pluggable and will not need any special configuration. The base model is ready now.

This model supports following features.
  1. Use of java annotations for injecting the resource. (A resource can be any object)
  2. No xml configuration is required (as there is no bean factory).
  3. Support for factory method for resource creation.
  4. Can create a singleton resource on demand.
  5. Lazy bean (resource) instantiation (unless specified as singleton).
All these features can be used by just declaring a runtime annotation (named 'IoCResource') on setter method of a resource. The backbone of this project is an interceptor which has to be included for the desired action in xwork.xml (you can even add it in a default interceptor stack). This interceptors interrogates the action class to be invoked and checkes if there is any setter method present which is marked with the IoCResource annotation. Any such method found, the interceptor tries to instantiate the resource by the method specified in the annotation. Then the interceptor will actually inject the resource into the OgnlValueStack, instead of directly injecting it into the action class instance. The webwork framework then takes care of it and automatically inserts it into the action class using setter method. The resource types supported are..

  1. SINGLETON : Creates and maintains a single instance of the resource
  2. FACTORY : The resource has to be instantiated using factory method
  3. DEFAULT : A simple bean resource
Here is a sample action class which makes use of this IoC mechanism to get the resources.

package com.yogesh.container.test;

import com.opensymphony.xwork.Action;
import com.opensymphony.xwork.ActionSupport;
import com.yogesh.container.annotations.IoCResource;
import com.yogesh.container.annotations.ResourceType;

public class TestAction extends ActionSupport {

static final long serialVersionUID = -3473501884603263686L;

private Resource resource;

@IoCResource(Type=ResourceType.DEFALUT)
public void setResource(Resource resource) {
this.resource = resource;
}

public Resource getResource() {
return resource;
}

public String execute(){
//Do some work using resource
return Action.SUCCESS;
}
}


If not specified, the type of the annotation IoCResource will be default (ResourceType.DEFAULT). Other options which can be defined in the IoCResource are...

Class : Name of the class of the resource. Generally not required.Can be used to instantiate object of subclass of the argument object class.

FactoryClass : Name of the factory class which will create the resource. This should be used if Type is ResorceType.FACTORY

FactoryMethod : Name of the factory method which will actually create the resource. Has to be used in conjunction with FactoryClass

So if there exists a factory class which can return an instance of the resource, the annotation can be declared as

@IoCResource(Type=ResourceType.FACTORY,
FactoryClass="com.yogesh.container.test.ResourceFactory",
FactoryMethod = "getResource")

I am releasing this project under GPL version 2 and looking out for some webspace to upload it. I will put a link in this blog if I get some.

By that time, happy coding.

Yogesh Pandit

No comments: