s2-logoUsing Spring, it is easy to inject any instance with its dependencies, as long as the instance is managed by the Spring container. This typically means that the to-be injected beans are configured in the XML configuration. However, sometimes, it is impossible or ugly design to have objects managed by the Spring container. For example, when using a Rich Domain Model , your application will instantiate domain objects that contain domain logic, and thus need their dependencies to be injected.

A commonly seen strategy to inject these dependencies is to call a static method from the constructor. This static method will inject the newly instantiated instance with its dependencies using a reference to Spring’s application context. Although this method seems effective, it is purely limited to dependency injection. Spring offers a lot more, such as transaction support and security.

Spring’s load time weaving capabilty offers a more complete way to inject your unmanaged instances, making them no different than any spring managed instance.


Configuring Load Time Weaving
Load Time Weaving (LTW) is the process of modification of byte code the moment a class is loaded and is often seen in AOP. When a class is loaded from disk and placed into memory be a ClassLoader, the byte code is evaluated and, if necessary, modified before it is made available to the application.

Enabling Spring’s load time weaving can be very simple. When you’re unlucky, it can get a little harder, but still easy. All you need to do is add the following to your application context:

<context:spring-configured/>

That can’t be all, can it? Well, that depends of the classloader loads your application. Spring will autodetect the classloader, and depending on the implementation, tell it to modify classes before loading them into memory. Unfortunately, not all class loaders are compatible with this approach.

According to Spring’s documentation, this method is compatible with the class loaders used by WebLogic 10, Oracle OC4J and Glassfish. If your class loader is not in this list, don’t worry, there is still hope. Tomcat users can configure Tomcat to use the TomcatInstrumentableClassLoader by putting the spring-tomcat-weaver.jar in the common/lib folder and adding the following snippet to META-INF/context.xml in the WAR root:

<Context>
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
            useSystemClassLoaderAsParent="false"/>
</Context>

This tells Tomcat to use another ClassLoader, which Spring can use to perform the weaving. See Tomcat Documentation for more about this type of configuration.

Another way to keep the ability to inject dependencies to unmanaged classes, is by instrumentation. Ben has written an article about how this works. Spring offers a JAR file that does the proper JVM instrumentation to allow load time weaving using any class loader. When starting your application, use the -javaagent:/path/to/spring-agent.jar parameter to load the LTW agent.

Dependency Injection configuration
Now that we have Spring watching our newly instantiated instances, we have to tell it how to inject them. That is, with which objects.

Independent of the option you choose, you have to annotate the class with @Configurable. This tells Spring that this unmanaged class is configurable using the Spring Application Context.

If you want to use auto wiring, all you need is to put the @Autowired annotation on either the setter or the field. Don’t forget to add the annotation support to your context, for example with the <context:annotation-config/> element, or the AutowiredAnnotationBeanPostProcessor.

You can also configure your unmanged class using XML configuration. Here is an example:

The java file:

@Configurable
public class DomainClass {

  private transient SomeDependency someDependency;

  // some logic

  public void setSomeDependency(SomeDependency someDependency) {
    // default setter logic
  }
}

The XML configuration:

<bean class="my.DomainClass" scope="prototype" abstract="true">
    <property name="someDependency" ref="someDependency"/>
</bean>

Notice that the property is made transient. I’ve done this, because this property shouldn’t be persisted or serialized. When the object is deserialized, Spring will automatically wire the object again. The same thing goes for persistence.

Spring will be able to relate this bean configuration to the newly instantiated class (through the id, which is defaulted to the class name) and wire your newly created instance according to the XML configuration. If you prefer to be more explicit, you can pass the id of the prototype bean in the value property of the @Configurable annotation. This will force Spring to look for the definition with the given bean id.

Dependencies
Almost forgot, if you want to use load time weaving, you need spring-aspects, aspectjrt and the usual spring jars on your classpath.

AOP using AspectJ
The good news is that you’re very close to being able to use AspectJ now. All you need to do now is configure the appropriate aspects and classes to weave using the META-INF/aop.xml files. It is beyond the scope of this article, but I couldn’t resist pointing you in the right direction.

Tagged on:

13 thoughts on “Injecting Domain objects with Spring

  • June 13, 2011 at 9:12 am
    Permalink

    Hi,

    If I add a method in my unit test class which contains the entity as one of the parameters why the dependency won’t get injected ?

  • March 17, 2010 at 6:31 pm
    Permalink

    Hi Allard,

    I just solved my problem with your nice Article.
    In my case, i’m using weblogic 10 and i wanted to inject the beans into the PageFlowController’s

    Thank you and congratulations for the great job.

  • Pingback: Gridshore » The power of immutability in a Rich Domain Model

  • February 2, 2009 at 10:44 pm
    Permalink

    Hi Allard,
    It’s true one has to be careful when instantiating new objects and from your comments in here and James’s blog I’m swayed to conclude that @Configurable provides the better option. Thanks to you and James for interesting and useful entries.

  • January 30, 2009 at 5:47 pm
    Permalink

    Hi James,

    I have to admit I have been reading your blog at a high-pace, so I had probably missed what you just said. It is still on my to-read list. Thanks for your comment!

  • January 30, 2009 at 1:48 pm
    Permalink

    Hi Allard
    Author of “solution #4″ here. I enjoyed reading your article.

    With the risk of being slightly off topic, I just want to clarify one point regarding my blog article mentioned above.

    The solution from my post (number 4) does not do DI for Hibernate instantiated objects only. Instead, we tell Hibernate to use our factories to DI the newly instantiated beans. This way, both a factory method and a Hibernate instantiated bean use the same DI code.

    If you were to create a bean for the first time, you would be using the factory and hence the object would also be dependency injected.

  • January 29, 2009 at 7:07 pm
    Permalink

    In Reply to Ben and Twice:

    The spring-aspects jar also contains some abstract aspects that you can implement to define your own wiring. That way, you do not have to depend on the @Configurable annotation. Personally, I don’t really mind having a dependency on Spring. How big are the odds of you changing the IoC framework? If so, you’ll have to do such a big refactoring, that removing the annotation is just a little extra effort.

    The problem with James’ solution #4 is that you only have dependencies injected when you retrieve an object from your hibernate session. When instantiating a new object, these dependencies are not available yet.

  • January 29, 2009 at 4:32 pm
    Permalink

    In reply to Anders S:

    I am currently building a small application using Domain Driven Design, just to get a feel for the point of view of “the other guys”. I (still) am a “separate infrastructure and domain” type of guy too. However, I do see that there is a valid point in DDD when they talk about reusability. DDD looks a lot dryer, but you do seem to get a lot of mixing of concerns in return. Spring’s easy-to-do Load Time Weaving might offer an option here. I’ll give DDD a chance, and you’ll see my results on this blog as soon as I am done investigating.

  • January 29, 2009 at 12:05 am
    Permalink

    Nice article.James Blewitt has also written another article here that explores the available domain injection options. I found his option 4 interesting and might go some way in addressing Ben’s concerns.

  • January 28, 2009 at 10:22 pm
    Permalink

    Allard,

    Good stuff; I know from experience how nice it would be from time to time to be able to inject managed resources into the domain layer, so I definitely like the concept. Also, I knew Spring had introduced LTW support but have never looked at it in-depth, so thanks for a clear and short article on how to get it working.

    The only thing I don’t like about the current set-up, though, is that it relies on an annotation. This visibly binds the code to Spring in return for DI only. For that reason, if I were to use LTW, I would consider going the last few meters and using AspectJ — as you suggest. It’s still binding to a framework that can provide the capability, but you get a little more bang for your buck.

    Thanks again!

    Ben.

  • January 28, 2009 at 4:58 pm
    Permalink

    Interesting stuff. I have been thinking about doing the same thing, but I’m not sure I like it. My main objection is that by making this easy it will be used all the time. And letting anyone inject anything in the domain objects will probably lead to a lot of mixed tests with mocking in the long run. I like to keep my domain and infrastructure separate, but I know this is a huge debate.

  • January 27, 2009 at 3:52 pm
    Permalink

    Jettro, I still do believe that DDD is a good solution to minimize the complexity in the questionnaire case. I did encounter some difficulties (DI was one of them), but as I manage to solve them, DDD seems more and more interesting.

  • January 27, 2009 at 3:38 pm
    Permalink

    Very interesting, does this change your opinion on the domain driven design case for questionnairs? Can it be done?

Comments are closed.