Tuesday, June 26, 2007

Configuration-hell remedy with Singleton injection

One of the most heard complaints about Spring projects is the seemingly unavoidable configuration-hell that silently creeps in every bigger project after some time.
Singleton injection is a simple practice that can significantly reduce configuration and corresponding injection code. Besides that, it provides possibilities you might not have been aware of enabling you to get most out of Spring. In this blog you will learn which advantages Singleton injection provides. It illustrates how to implement it and specifies clear guidelines in which circumstances it is applied best.
Where applicable, Singleton injection can be an elegant solution that provides significant code and configuration simplification.
At the beginning of a Spring project, when the applicationContext.xml(s) resemble a fallow field, it is easy to keep the overview of your beans. As time goes by most of us have been facing the configuration-hell growing out of proportion, making it difficult to find your way in the bean jungle. There are several commonly applied best-practices to postpone this problem as long as possible, such as the usage of abstract declarations, splitting up the bean configuration in several subconfigurations or Eclipse’s Spring IDE.
Besides that I have come across another way, which can significantly contribute to reduce spring configuration, eliminate superfluous code and provide other interesting advantages you might not have been aware of before. The way to achieve that is called Singleton injection.

The familiar way

Consider the following piece of code and configuration:
public class AnyService {
    private Logger log = Logger.getLogger(AnyService.class);
    private MessageResource messageResouce;

    public setMessageResource(MessageResource messageResouce) {
        this.messageResouce = messageResouce;
    }
    public void execute() {
        if(condition)
            log.error(messageResource.getMessage("error.msg.key.1"));
        //  more code 
    }
}

public class AnyDAO {
    private Logger log = Logger.getLogger(AnyDAO.class);
    private MessageResource messageResouce;

    public setMessageResource(MessageResource messageResouce) {
        this.messageResouce = messageResouce;
    }

    public List findAll() {
        if(condition)
            log.warn(messageResource.getMessage("error.msg.key.2"));
        //more code
    }
}
<!-- configuration -->
<!-- message resource implementation -->
<bean id="messageResource" class="com.xebia.example.MessageResourceImpl">
    property name="resourceLocation" value="classpath:/bundle.properties"/>
</bean>

<!-- classes using the message resource -->
<bean id="aService" class="AnyService">
    <property name="messageResource" ref="messageResource"/>
</bean>
<bean id="aDAO" class="AnyDAO">
    <property name="messageResource" ref="messageResource"/>
</bean>
<!-- ...and many more -->
Apparently, the MessageResource class is used throughout the application, actually by each class that needs to log something. Since we want to initialize the MessageResource class with the proper configuration with the BeanFactory facilities, we configure the MessageResource class as a spring bean and inject it in every class that makes use of it. The latter is followed by tedious instance variable/setter code and injection configuration. This should sound familiar to you.

The alternative: Singleton injection

Fortunately, there is an easier way. Consider the following piece of code:
public class AnyService {
    private Logger log = Logger.getLogger(AnyService.class);

    public void execute() {
        if(condition)
            Log.error(MessageResourceSingleton.getInstance().getMessage(“error.msg.key.1”));
        //  more code 
    }
}
As you can see, most of the spring-related injection hassle seems to have disappeared. At least, that might be the first impression. Instead of cumbersomely injecting the MessageResource bean in all classes that use it, we take a slightly different approach:
1. We write a wrapper class applying the Singleton pattern (here MessageResourceSingleton) that wraps an implementation of the MessageResource class
2. Then add configuration that injects the implementation (MessageResource) into the Singleton wrapper (MessageResourceSingleton)
The following code and configuration illustrates the Singleton injection approach:
public class MessageResourceSingleton implements MessageResource{

    /** MessageResource implementation to be injected  */
    private MessageResource messageResource;
   
    /** singleton instance */
    private static MessageResourceSingleton singleton = new MessageResourceSingleton();
    /**
     * Gets singleton
     * @return singleton
     */
    public static MessageResourceSingleton getInstance(){
        return singleton;
    }
    /**
     * Setter for the MessageResource implementation used to inject
     * the implementation
     * @param messageResource
     */
    public void setMessageResource(MessageResource messageResource) {
        this.messageResource = messageResource;
    }
    /**
     * Delegates the call to the injected implementation
     * @param args arguments
     * @return message
     */
    public String getMessage(String key) {
        return messageResource.getMessage(key);
    }
}
<!-- configuration -->
<!--  Singleton that gets the message resource implementation injected. Note the usage of factory-method. The factory-method calls the static method getInstance() of the singleton returning the singleton instance -->
<bean id="singleton" class="com.xebia.example.MessageResourceSingleton" factory-method="getInstance">
    <property name="messageResource" ref="messageResource"/>
</bean>

<!-- message resource implementation -->
<bean id="messageResource" class="com.xebia.example.MessageResourceImpl">
    <property name="resourceLocation" value="classpath:/bundle.properties"/>
</bean>


Any class that wants to use the MessageResource implementation simply calls:
MessageResourceSingleton.getInstance().getMessage(“any.key”);

By doing so, we can use all the configuration power spring provides when defining the implementation bean. The code, which uses the implementation, is not only freed of superfluous injection code and corresponding configuration but is – as the IoC principle demands –totally unaware that Spring is pulling the strings (or beans ;-) ).

Your gains with Singleton injection

So, when using Singleton injection these are your gains:
  • Reduced configuration and less code (inject once use everywhere)
  • Injected Singletons can be used in classes that are not part of the beanwiring chain
  • Static methods can use injected Singletons
  • Injected Singletons can serve as beanwiring starting points
  • Increased productivity (instant usage of injected code)

Since it all seems so simple, practical and advantageous, why not use Singleton injection everywhere in you code?

When to use Singleton injection

The tradeoff when considering Singleton injection is simplicity versus flexibility. The constraint is that the Singleton can only wrap one specific implementation. Therefore, every class that makes use of the Singleton wrapper will have to stick with this particular implementation. You still can have several implementations available (for unittesting, mocking etc.) but at runtime only one of these can be used throughout the application.
In other words, when you face a “one size fits all” scenario you have a case for a Singleton injection. In more detail, the following preconditions have to be present in order to make Singleton injection a useful choice:
  • A spring bean is used in various, peripheral parts of the application
  • A spring bean has the characteristics of an utility class that needs to be initialized with external resources or other parameters
  • A spring bean has to be accessible by classes that are not part of the beanwiring chain
  • It is sufficient that at runtime only one specific implementation of the spring bean is used throughout the application

Real world cases for Singleton injection

I have used Singleton injection on various projects. The following type of classes have proven to be an excellent candidate for Singleton injection:
  • MessageResource utility like the one used in this example
  • Logger utility that needs to perform logging to a database or queue
  • IDGenerator that gets id’s used for logging or messaging from a database
  • CodeMapper that maps technical codes to a description
  • Business Delegate, which can be used as startingpoint of the beanwiring
  • Any utility you want to use in a framework or component, which does not provide hooks to inject spring beans (in case they are still out there…)

Conclusion

Where applicable Singleton injection can be an elegant solution that provides significant code and configuration simplification. Additionally, it enables you to profit from “Spring injection power” outside the standard beanwiring chain. All this can be achieved with such a simple thing like Singleton injection. It enables you to do more with less – isn’t this what programming is all about?
By Urs Peter

5 comments:

Bruno said...

So in order to reduce the amount of configuration (the amount of wiring of a single bean in many places in your code), you propose introducing a whole new class, for each bean that needs to be injected in this manner ?
Doesn't that sound a bit like overkill ?

Granted, having the possibility of accessing a bean from code that is not bean-managed, as you pointed out, is a good benefit. But in most Spring projects, every piece of the code is managed by Spring, so that doesn't occur often.

Also, wouldn't autowiring by type fix your problem just as easily, and with no new class needing to be introduced ? (albeit autowiring has its problems, but it nonetheless adresses this exact problem)

Les said...

This is a really bad idea and is exactly what Spring pojo-based Dependency Injection was created to avoid - to replace the Service Locator pattern. What you're providing in a static getInstance() call is essentially a type-specific Service Locator.

Statics are evil - they're inherently non-OO and usually encourage poor programming practices, especially the proliferation of unnecessary functional programming in an OO language. They should only be used to overcome poor programming situations outside of your control - i.e. a tool to use in an extremely limited basis only when you can't use something else.

And although what you describe might make your life easier in the immediate sense, it significantly complicates it in other ways. How, for example, would you unit test your code properly without introducing dependencies not required for the test? Cleaner instance-level DI allows you do do things such as creating mock objects and anonymous inner classes for testing that is not possible with static singletons or where you would have to change a lot of code.

If you want to make your life easy, use autowiring - that's exactly why it was created. The new Spring 2.0 XML namespaces also simplify things greatly, reducing XML config. And, with IDEs like Eclipse and IntelliJ IDEA that actually can traverse, manage, and refactor the XML spring files for you, the "XML Hell" argument for using Static singletons, especially when your own code suffers greatly in flexibility, is not really an issue.

Bottom line - never let laziness dictate your software architecture (especially when similar alternatives like autowiring exist), and stick with the pragmatic, well-thought and proven solution.

I just thought it important to raise the issue on this for anybody reading this blog entry, especially those relatively new to Spring. What you mention is _not_ a good idea for 99% of cases, and the less-experienced Spring folks shouldn't be led down a misleading path.

Jean-Christian Gagné said...

Well, I like good OO designs and theories, but I must say that I also used the "singleton injection" pattern described here and I feel very comfortable with it, and I'm not a Spring newbie...

Even with Spring 2.0 new features, having ALL beans managed by Spring IS overkill, and in many case not necessary, unless you consider that obtaining a bean using "new" is not OO.

Suppose you have a bean that uses a bean that uses another bean... and so on. Only the lates needs injection. Does it really make sense to have all those beans spring-managed ? I don't call this pragmatic.

For unit tests, I can easily use mock objects using a test-only spring context, or manual injection. It's true that it introduces an unnecessary dependency, but I prefer this to having unnecessary XML.

Someone said that a good developer was a lazy developer : he always choose the simplest solution. (in a book called Pragmatic programmer?)

I consider this a nice shortcut to benefit from all the power of DI without XML overkill.

It's true that statics are evil, but singleton pattern IS an OO pattern. Use it but don't abuse it.

Jean-Christian Gagné

Jean-Christian Gagné said...

As a follow-up, I must say that Spring 2.5 support for annotations greatly reduces the need for the singleton injection pattern. Have a look at @Component, @Resource, etc. Annotated pojos = injection everywhere with very little XML.

Phil said...

Isn't it more logical to have and return a single instance of the resource itself (messageResource) than an instance of the singleton? Yes you don't have to produce a lot of getter/setter code but instead you have to write delegate methods which is not so transparent (it's faster to generate getter/setter in the IDE than to write delegate method for each original method).