Configuration-hell remedy with Singleton injection

Urs Peter

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?

Comments (4)

  1. Age Mooy - Reply

    October 19, 2006 at 9:23 am

    Why would you not use an abstract bean definition for shared properties ? That's exactly what they are for and it's a much more flexible solution. Using semi-classic singletons with static accessors only unnecessarily ties you to creation logic and one implementation.

  2. Lonneke Dikmans - Reply

    October 19, 2006 at 7:28 pm

    I agree with Age. For the messageresource utility:: if you want to log something in every class you have a crosscutting concern. Spring offers possibilities for that: aspects. Why don't you use that?

  3. Vincent Partington - Reply

    October 19, 2006 at 10:26 pm

    Same agreement here.

    - The configuration duplication can be addressed by using either an abstract bean definition (as Age suggests) or auto-wiring.
    - The code duplication can be addressed by using an abstract superclass. If that is not feasible you can use AspectJ 5's inter-type member declarations to introduce setters and getters, although I'm not entirely sure I really like that. And, finally you can use AOP to properly implement the crosscutting concerns as Lonneke suggests.

    This singleton approach has the big disadvantage that it is makes it impossible to untie all the classes that use that same singleton without changing the code. The whole point of DI is that the object graph and the singletons in it are declared in a configuration file.

    Regards, Vincent.

  4. Olivier Croisier - Reply

    September 4, 2008 at 12:02 pm

    Altough I don't really like this solution, using by-type autowiring can also help declutter the configuration files. Crosscutting utility classes like loggers can then be automatically injected, whereas the rest of the injected refs/values can still be configured by hand.

Add a Comment