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

Migrating to Spring 2: Part 3 - injecting dependencies into entities

posted Wednesday, 15 February 2006

Regular dependency injection works well when you are injecting dependencies into static components such as services and repositories/DAOs, which are created by Spring.  But what about objects that are not created by Spring? Quite often these objects also have dependencies. For example, in the POJOs in Action domain model, the PendingOrder domain entity uses the RestaurantRepository. It calls RestaurantRepository.isRestaurantAvailable(deliveryInformation)  to verify that the the supplied delivery information is served by at least one restaurant. In this example, I solved the problem by having the PlaceOrderService, which is created by Spring and can use dependency injection, pass the RestaurantRepository as an argument to the PendingOrder.updateDeliveryInfo() method:


public class PlaceOrderServiceImpl
 
 public PlaceOrderServiceResult updateDeliveryInfo(String pendingOrderId,
         Address deliveryAddress, Date deliveryTime) {
    PendingOrder pendingOrder = findOrCreatePendingOrder(pendingOrderId);
    int result = pendingOrder.updateDeliveryInfo(restaurantRepository,
                                                 deliveryAddress, deliveryTime, false);
        ...
        }
...
}


Unfortunately, passing dependencies as parameters is not always this simple because the method that uses the dependency  can be many methods calls away from the service. Either we need to pass the dependencies as extra parameters, which clutters the code, or the methods must access them via statics, which have their own drawbacks. Neither solution is ideal. This is where Spring 2 comes to the rescue.


One of the more interesting features of Spring 2 is its support for injecting dependencies into entities.  Spring 2 uses AspectJ to intercept calls to an entity's constructor and initializes it with setter injection. To use this feature with PendingOrder we need to do three things. First, we replace the method parameter with a restaurantRepository property and add the @Configurable annotation to the class:


@Configurable("pendingOrder")
public class PendingOrder {


  private RestaurantRepository restaurantRepository;


  public void setRestaurantRepository(RestaurantRepository restaurantRepository) {
    this.restaurantRepository = restaurantRepository;
  }
 
  public int updateDeliveryInfo(
            Address deliveryAddress,
            Date deliveryTime,
            boolean force) { ... }
...
}


The @Configurable attribute tells Spring to inject dependencies into instances of the PendingOrder class using the bean definition named "pendingOrder".


Second, we need the following XML in the Spring application context:


 <aop:spring-configured />


 <bean id="pendingOrder" lazy-init="true">
  <property name="restaurantRepository" ref="RestaurantRepositoryImpl" />
 </bean>


The <aop:spring-configured/> element enables dependency injection into entities. The <bean id="pendingOrder"> definition specifies the values to inject into the PendingOrder using setter injection. The id of the <bean> matches the name specified in the @Configured element.


Third, we need to use AspectJ to weave into the PendingOrder class's bytecodes the Spring-supplied aspect that is triggered by the @Configurable annotation . There are a couple of ways to do this. One option is to use the AspectJ compiler to compile the domain model with the Spring aspect library. The second option, which is the one I chose, is to use AspectJ's load-time weaving feature, which weaves the aspects into the application's classes when they are loaded.  Load-time weaving is enabled using the "-javaagent:aspectjweaver-1.5.0.jar" command line option and including this META-INF/aop.xml file in the class path


<aspectj>


 <weaver options="-verbose">
  <include within="net.chrisrichardson.foodToGo.domain.*" />
  <exclude within="*..*CGLIB*" />
 </weaver>


</aspectj>


The <include> and <exclude> elements restrict load-time weaving to only classes in the net.chrisrichardson.foodToGo.domain package that are not Hibernate's cglib generated proxies. This speeds up class loading.


After making these changes, Spring injects the RestaurantRepository into any instances of PendingOrder that are created by either the application or by Hibernate. The PlaceOrderService no longer needs to pass the RestaurantRepository to the PendingOrder as a method parameter.


Injecting dependencies into entities eliminates the clutter caused by passing them around as method parameters. However, there are some issues to consider.  It requires using AspectJ byte-code weaving either via the the AspectJ compiler, which can impact your build mechanism, or via load-time weaving, which can slow down program startup. Also, you probably want to continue unit testing the domain model without Spring, which requires changing the code to manually inject dependencies. For example, code that instantiates and invokes methods on the PendingOrder must inject the RestaurantRepository. This will be the topic of a future post.

links: digg this    del.icio.us    technorati    reddit




1. Dan Haywood left...
Wednesday, 15 February 2006 3:23 pm

Good blog Chris. We've been doing something similar on my current project (http://www.danhay wood.com/blog/default/?permalink=A-word-from-our-sponsor.html), although since we're not using AspectJ the way we do it is to create our domain objects through a container, and then it inspects them to see what they are aware of. So, your PendingOrder would implement RestaurantRepositoryAware, which in turn would define a method setRestuarantRepository(). In this way our container which is instantiated by Spring, propogates its dependencies into the domain entities that it creates.

One thing that we haven't managed to address to my satisfaction though is how to inject dependencies for static methods. For example, we would have a method: public static PendingOrder create(...) in the PendingOrder class. This might need to use the RestaurantRepository. It seems there's only really two options here: (a) pass in the repository or (b) bind it to a thread-local. We've gone for option (b), but it is a bit of a code smell IMHO.

Interested in your thoughts. Dan


2. Cristian Pascu left...
Tuesday, 7 March 2006 5:33 am :: http://wedge.sf.net

Hi, Chris! I do not want to bother you too much but I was curious about what you think on having pojo's in the presentation layer of an application. As you know, JSF enables you to work with simple POJO as managed beans. But as Tapestry proves it, it is possible to also have clean xhtml templates for the pages. But then, Tapestry impose an unnatural programming paradigm as it requires pages to be abstract and to extend a framework class. I think it would be great if it were possible to have both java code and xhtml templates cleanly separated (tapestry or wicket style of separation) from each other and to also have a free object hierarchy on the java side.

There is this project I am working on in which I am trying to achieve that. And I have got pretty far with it. All the application pages objects are simple POJO's and are managed by Spring IOC.

I'll be glad to find out which is your opinion on this subject!

Thank you very much!


3. POJO Mojo left...
Sunday, 26 March 2006 1:47 pm :: http://stepaheadsoftware.com

Hi Chris, I have a question about the use of dependency injection. There certainly seems to be a lot of declarative 'coding' required to set up injection for any POJO that uses a repository and the POJO objects themselves need to have a property added to store the dependency (eg., RestaurantRepository in the PendingOrder POJO) whereas a ThreadLocal solution uses just a simple static call to retrieve an repository. I have seen a few examples using ThreadLocal to tackle this issue and it seems to work fine. I can understand the code "smell" associated with singletons but a ThreadLocal solution avoids the multithreaded problems and (I'm guessing here!) with a smart approach you could apply the Template pattern to the ThreadLocal's reference allowing the solution to be more testable.


4. cyboc left...
Tuesday, 22 August 2006 11:34 am :: http://joesbitbucket.blogspot.com/

Thanks so much! Until I read your entry, I was unaware that dependency injection of domain objects instantiated outside the Spring container would be officially supported in the upcoming release of Spring 2.