Chris Richardson - enterprise POJOs

My book

Calendar

««Aug 2008»»
SMTWTFS
      12
3456789
10111213141516
17181920212223
24252627282930
31

My Top Tags

                                                                               

My RSS Feeds








 

I run a consulting and training company that helps organizations build better software faster.

We provide a variety of services including:

  • Development - we can build your application for you
  • Deployment - we can find a hosting partner or deploy your application on Amazon EC2
  • Training classes for Spring, Hibernate and Acegi Security
  • Jumpstarts to get your project off to the right start
  • Reviews to improve your architecture, code and development process

For more information contact me.

 

My bookmarks

Mailing List

Simplifying Spring's XML-based dependency injection

posted Tuesday, 24 April 2007

XML Spring bean definitions can be verbose. However, an important benefit of using XML is that it completely decouples the components that are being assembled from the mechanism that is assembling them. This is an important part of the POJO programming model and would allow, for example, Spring to be easily replaced by some other framework. This is not true when using annotation-based dependency injection such as that provided by the Guice framework. Components that use those kinds of annotations are tightly coupled to the framework and are definitely not POJOs!

So how can we use a more concise form of XML for configuring dependency injection? In my recent projects, most components had pretty simple wiring rules, e.g. services are injected with repositories; repositories are injected with the SessionFactory or HibernateTemplate etc. Moreover, there is usually a single instance of each bean class and so it's possible to autowire components. We could, therefore, define each service with something like this:

<bean name="fooService" autowire="constructor"  class="FooServiceImpl"/>

This is certainly easier that writing multiple <constructor-arg> elements and updating them as the class changes. But we would have to write and maintain similar XML for every component. Why not go one step further and write a "rule" to define beans for all of the components?

Writing "rules" to configure multiple beans

Here is an example of such a "rule":

 
<beans>

<arid:define-beans

   package="net.chrisrichardson.arid.example.dao"

  autowire="byType"

/>

</beans>

 
The <arid:define-beans> element (arid is a custom Spring XML namespace) generates bean definitions that use byType autowiring for all of the concrete classes in the net.chrisrichardson.arid.example.dao package. Each bean would, for example, be injected with a Hibernate SessionFactory. The bean name is derived from the concrete class name using a pluggable algorithm - the default algorithm generates a bean called accountDao for the class AccountDaoImpl.

Using AspectJ type patterns

We can be a little more selective about which classes to define as Spring beans by using the <arid:define-beans> element's pattern attribute. This attribute is an AspectJ type pattern. We can use it to match against class names, classes annotations etc. Here is an example of that:

 
<arid:define-beans

package="net.chrisrichardson.arid.example.domain"

pattern="@ServiceImpl *..*">

</arid:define-beans>

 

This definition looks for classes in the net.chrisrichardson.arid.example.domain package that have the application-defined @ServiceImpl annotation (package name omitted for brevity) and defines beans that use constructor autowiring. Each bean would, for example, be injected with the necessary DAOs.

Handling special cases

But wait, there is more! Let's suppose that one of the classes needs to be injected with some property value. One option is to write a regular bean definition that overrides the definition generated by <arid:define-beans>. Alternatively, you can use <arid:extras> element. In the following example, the moneyTransferService bean uses constructor autowiring and setter injection for the foo property.

 
<arid:define-beans

package="net.chrisrichardson.arid.example.domain"

pattern="@ServiceImpl *..*">

    <arid:extras>

<bean name="moneyTransferService">

    <property name="foo" value="bar" />

</bean>

     </arid:extras>

</arid:define-beans>

 

The Spring bean definitions defined by <arid:extras> are merged with the autogenerated bean definition. I'm not sure whether this is worthwhile since it only saves you having to specify the class and autowire attributes but it's something to think about.

Summary

This approach can significantly reduce the amount of XML required to configure an application. However, how widely it can be used in your application depends on whether the same dependency injection rules can be consistently applied to multiple beans. Would this help simplify your application's Spring configuration files?

tags:                  

links: digg this    del.icio.us    technorati    reddit




1. Matt Raible left...
Tuesday, 24 April 2007 7:56 am :: http://raibledesigns.com

I could see this as being useful - especially in something like AppFuse where there's a pre-defined set of patterns/conventions to follow.


2. Craig Walls left...
Sunday, 29 April 2007 6:28 pm

This sounds interesting...is it a real configuration namespace you have? Or is it just something that you're proposing? If it's real, where can I get it and try it out?


3. Ivan Lazarte left...
Tuesday, 1 May 2007 3:10 pm

Wow. I *love* discovering excellent ideas like this one. Now it's just a race to get this in production and relieve the xml burden :). Have you considered approaching the spring team with this as a patch?


4. Chris Richardson left...
Tuesday, 1 May 2007 3:16 pm

If you would like to try it out, you can get the source code from here: http://code.google.com/p/aridpojos/


5. Tyler Nelson left...
Thursday, 3 May 2007 7:40 am

This looks money. I was having a discussion with a coworker the other day about a similar idea. One question though, can this support one class that is reused multiple times in an app context. For example we have a generic hibernate dao that we wire up with different parameters like the class to use, etc. Could this be used in that case?


6. Michael left...
Thursday, 3 May 2007 9:16 am :: http://fupeg.blogspot.com

This is a clever idea, but objects auto-wired in this fashion are only superficially "more POJO like" than objects wired via annotations (as in Guice or EJB3 for that matter.) You have a hidden dependency on your DI runtime (Spring) and on a packaging convention. At least with an annotation approach, the dependencies are more explicit even if they are intrusive. In terms of maintainability (code you wrote being maintained by other developers next year, etc.) one can argue there are advantages to being more explicit.


7. Chris Richardson left...
Thursday, 3 May 2007 12:57 pm :: http://chris-richardson.blog-city.com/

Tyler,

Your question about wiring Generic DAOs is interesting. What does your Generic DAO look like?

I am working extending Arid to let you plug in a different bean definition generation algorithm. This might be able to generate a DAO Spring bean for each of your persistent classes. Stay tuned.

Chris


8. John Zhang left...
Wednesday, 9 May 2007 8:34 am

What if my interface and impl class reside in different packages? For example, interface at com.xxx.dao and impl at com.xxx.dao.hibernate (or com.xxx.dao.ibatis).


9. Lucio Benfante left...
Friday, 11 May 2007 10:24 pm :: http://www.benfante.com

Great idea, thank you! I applied in Parancoe framework (parancoe.dev.java.net) for obtaining auto-discovering of persistent classes and auto-definition of DAOs. If you are interested, there is a tutorial in our wiki about using this part of Parancoe: http://wiki.java.net/bin/view/Projects/ParancoePersistenceTutorial .

Thank you again Kind regards,

  • Lucio


10. Alberto Mijares left...
Thursday, 10 January 2008 5:06 am

This is a great idea but I see it difficult to know when it is working right and to document it for future maintenance. Two ideas for getting some graphical solution (A picture is worth a thousand words): Spring IDE integration (maybe not easy or useful), Apache Camel Visualization approach (see http://activemq.apache.org/camel/visualisation.html). The second integrates GraphViz through a Maven plugin and Chris, you look a Maven guy :O)