Sunday, March 14, 2010

Dependency Injection and JPA

Consider the following classes


These are POJOs and also JPA entities.
Note that ShortPerson has a (transient) Ladder dependency.
When the JPA EntityManager loads the ShortPerson instances it does not supply the Ladder objects, thus when invoking the getObjectFromTopShelf() method on the short person object will fail.

I haven't found a best-practice on how to inject my dependencies.

I could write code in the ShortPerson constructor that "pulls" the dependency from the container, but that adds a dependency on the container, which must be initialized properly
before I create my ShortPerson instance.

So it should probably be done in the DAO, but how? Only one of my classes has the setLadder() method.


My solution is a combination of pulling the dependencies but from a runtime object.
Have another object (let's call it injector) know all of the possible dependencies of the various Person objects, and have each object pull it's own dependency from the injector.




So now Person has an empty implementation for inject() and ShortPerson can pull its ladder implementation from the injector, still decoupling ShortPerson from the dependency injection framework.
After the DAO loads the entities and before returning them to the client it invokes the inject() method for each instance.

The DAO itself can have the injector implementation injected into it during instantiation.

List persons = em.createQuery( "from Person" ).getResultList();
for ( Object object : entlist )
{
   Person person = (Person)object;
   person.inject( injector );
}

5 comments:

  1. http://amin-mc.blogspot.com/2008/02/configurable-example-with-spring-25.html

    ReplyDelete
  2. You can try Salve:
    http://code.google.com/p/salve

    ReplyDelete
  3. Thanks Kris, this is a very good example of how to use Spring to inject dependencies to domain objects.

    ReplyDelete
  4. Thanks Juan, Salve also looks like a good solution to this problem. At first glance I would go with Spring but that's because I already use Spring in my application.

    ReplyDelete
  5. It is crappy that or mapper don't expose a factory when entities instances are created. Adding such a factory would make it a lot easier to integrate DI frameworks.

    Peter Veentjer
    Multiverse: Software Transactional Memory for Java
    http://multiverse.codehaus.org

    ReplyDelete