Browse DevX
Sign up for e-mail newsletters from DevX


The Why and How Behind Listener-Based Dependency Injection : Page 2

Listener-based dependency injection builds upon the core concepts of property-based Dependency Injection and offers many of the same benefits. Find out how you can use listener injection to reduce boilerplate code and clearly communicate relationships between POJOs using the Spring framework.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Staying True to the POJO Model
The PollManager interface from JPoller has nine methods, of which only two are of interest to the example application previously discussed. Not only does this force you to implement several empty methods, it also violates the Inversion of Control you typically associate with dependency injection. A framework (in this case JPoller) is requiring you to implement a specific interface as an implementation technique. The goal of a POJO programming model is to minimize these sorts of requirements from frameworks.

Here too, listener injection can help. You actually aren't required to implement the listener interface at all. As a first step, consider an example where you define a POJO with the two methods you are interested in from the PollManager interface. The class would look as follows:

public class Callback { public void fileFound(FileFoundEvent evt) { ... } public void fileSetFound(FileSetFoundEvent evt) { ... } }

Notice you are not implementing the PollManager interface at all, just providing the two methods of interest with the same names and signatures. You just need to specify the mapping of methods in which you are interested, from the PollManager interface to your Callback in configuration (see Listing 2).

The bold section of the configuration in Listing 2 shows you mapping methods to your POJO. By not specifying mappings for the other methods, those invocations are silently dropped. This is really great in that it reduces boilerplate code, yet still provides some coupling that ties you specifically to JPoller. That is, the FileFoundEvent and the FileSetFoundEvent objects still reflect a compile-time dependence on the JPoller libraries. If you could remove your dependence on these objects, you would be able to use JPoller as an implementation while maintaining loose coupling with your POJO programming model.

So for the third and final example, change the callback more severely by defining the methods you want to define without using any JPoller-specific classes as either an ancestor or in the method signatures:

public class Callback { public void handleFile(Object src, File f) { ... } public void handleFiles(Object src, File[] files) { ... } }

Notice that your callback methods, in addition to using different names, don't even have the same number of arguments in the method calls. Still with listener injection, the mapping is straightforward (see Listing 3).

In Listing 3, you can see the map-method section is fleshed out a little more. The method name mapping is the same as in Listing 2, but there's also a section listing arguments. These arguments correspond to the arguments that will be passed into the new method on the callback class. Under the covers, listener injection is using the Jakarta Commons beanUtils notion of nested properties.

In the first mapped method, the fileFound method is mapped to the handleFile method. The first argument passed into handleFile will be the poller bean (as retrieved from the BeanFactory), while the second argument passed into handleFile is the file property on the FileFoundEvent. (For more details, see the javadocs of the BeanFactoryAwareGenericMessage and its parent GenericMessage, which is the actual object to which the nested properties are relative).

Now That You've Scratched the Surface...
This basic introduction to listener-based dependency injection is really just the beginning. With listener injection, you could also inject sophisticated listeners that, for example, adapt a POJO listener/callback style of programming for publishing to JMS destinations or for an ESB-based implementation—while preserving a unit-testable POJO class design. You could even start with an example like the one discussed at the beginning of this article and convert it to use JMS or an ESB entirely with configuration.

Bryant Harris is a Senior Architect/Development Manager who specializes in middleware and using software as a tool for executing business plans. Bryant also is the founder of the open source Classpath Helper project.
Thanks for your registration, follow us on our social networks to keep up-to-date