Archive for January, 2011

January 5, 2011

Spring: lookup-method injection

The first of my java posts.

Those who have been working with Spring for a while (or have even just started) will know that Spring instantiates all beans by default as Singleton. Now, there are scenarios wherein you would want multiple instances of a bean to be created (prototype) from within a singleton bean.
One approach is to have your singleton class implement BeanFactoryAware interface. However, that ties the code to spring; and believe me, you would NOT want to do that.

A second, better approach is to use lookup-method injection. Let us see an example below:
1. DirectoryPoller is a class which listens on a given directory in the file system for dropped files.
2. PollerMaker is a class which instantiates an instance of a DirectoryPoller.
3. PollerThread is a Thread instance which will be instantiated for every folder to be listened into.

Here are the code snippets from the above classes:
(Note DirectoryPoller is a third party class provided by Cristiano Sadun. Obtain DirectoryPoller and its dependent packages here.)


public abstract class PollerMaker {
/*
* Abstract method to create DirectoryPoller instance
* by lookup-method feature provided by Spring.
* This is done to avoid tying the code to spring using
* BeanFactoryAware interface. DirectoryPoller instances are
* created one per invoking thread i.e. one per file type.
*/
protected abstract DirectoryPoller
createDirectoryPoller();

public DirectoryPoller getPollerInstance(){
return createDirectoryPoller();
}
}

The above class is the abstract singleton used to retrieve an instance of DirectoryPoller each time the getPollerInstance() method is called.


private class PollerThread implements Runnable{
FileFoundListener fileListener;

PollerThread(FileFoundListener plugin){
fileListener = plugin;
}

public void run(){
//DirectoryPoller poller = (DirectoryPoller) factory.getBean("directory.poller", DirectoryPoller.class);
DirectoryPoller poller = maker.getPollerInstance();
poller.addFileFoundListener(fileListener, fileListener.getSearchDirectory());
poller.addDirectory(fileListener.getSearchDirectory().getAbsolutePath());
poller.start();
}
}

Now, for the Spring context configuration:

<!-- The extended Sadun DirectoryPoller to service out specific needs -->
<bean id="directory.poller" scope="prototype">
<property name="autoMove" value="true" />
<property name="pollInterval" value="2000" />
<!-- Set this property if this application needs to wait for another application to come up.
Use a java.util.concurrent.CountDownLatch instance with jdk5.0 and higher. -->
<!-- <property name="countDownLatch" ref="" />-->
</bean>

<!-- The lookup-method DirectoryPoller creator -->
<bean id="poller.maker">
<lookup-method name="createDirectoryPoller" bean="directory.poller" />
</bean>

On container instantiation, Springs ApplicationContext will load all the declared Singleton beans into the container.

*Tip*
Remember, that the Singleton which will invoke the Prototype instances has to be loaded by Spring, otherwise Spring will not override your abstract method using CGLIB to provide its own implementation.