Bernie's Blog A confusing concoction of Java, mobile devices, technology and photography

12Dec/090

Guice or Spring?

Just today, someone mentioned that becauseĀ Spring already does what Guice does (and more, I might add) that I should stick to the latter. I beg to differ. Each has its own purpose, I wouldn't put these 2 in the same league.

Spring is almost a complete container. From security, a web MVC model, batch framework, persistence, JMX, scheduling, web services and many more, Spring offers (or is able to piece together) an almost complete stack to build enterprise applications. In other words, it's a JEE competitor. Its selling point has always been as a lightweight enterprise stack anyway.

Guice on the other hand is a lightweight DI enabler, so to speak. It offers to take away DI code that a developer could otherwise write themselves. This is probably a gross over-simplication but that's how I see it. When I want DI or AOP but I don't want the whole she-bang (and I don't want to do DI manually), Guice is the solution. On the other hand, if I'm looking to develop enterprise software, I could use Guice, but Spring offers so many bundled services that it's hard to ignore.

I like how Guice encourages constructor injection (which, along with final fields, encourages immutability) and that it returns new instances by default - both of which should allow better performing apps when paired with powerful hardware (read: multi-core friendly). I also like how Guice encourages thinking of applications in Modules, its promotion of testability and its potential reusability. I'm a seasoned Spring developer but it was Guice that really made me step back and think about DI, testability and modularity.

After a few weeks of implementing a small library in Guice, it seems there's no turning back. For non-trivial stuff, there's Spring but for everything else, Guice may be the better choice for me. At the end of the day, Guice is yet another tool under my belt. To dismiss it entirely because I already know Spring is just foolish (even if I've been using Spring for 2 years). Of course, I'll also keep my eye on the recently announced JSR that will bring DI to standard Java.

Guice and Spring are but tools. It's DI, AOP and testability that I need.

3Dec/095

Google Guice @Provider Gotcha

Note: Best read after some background reading on Google Guice and dependency injection.

I spent many hours pouring through my codes to resolve this so I'm posting this as a guide to others.

Scenario:

Google Guice allows Providers to be defined, either using the @Provider annotation or by implementing the Provider interface. To those new to Guice, here's a simple explanation on providers:

When you need code to create an object, use an @Provides method

In other words, when you need to inject an object that needs some sort of setup code, or when you need to customize what is injected, you resort to using a Provider. Here's a code snippet that injects a chain of handlers (read: Chain of Responsibility pattern):

@Provides
	private ErResponseHandler provideResponseHandlers() {
		// builds the handlers manually - chain of responsibility pattern
		ErResponseHandler handler = new InactivateAccountResponseHandler(
				new UsageAuthRateChargeResponseHandler());
		return handler;
	}

And this is BaseResponseHandler - a base class which implements ErResponseHandler.

public abstract class BaseResponseHandler implements ErResponseHandler {

        @Inject
	protected XmlBinder xmlbinder;

	public BaseResponseHandler() {
	}
	private ErResponseHandler next;
	public BaseResponseHandler(final ErResponseHandler nextHandler) {
		this.next = nextHandler;
	}
	public final boolean start(final ErResponse response) {
		boolean handled = this.handleResponse(response);
		if (next != null && !handled) {
			next.start(response);
		}
		return handled;
	}
	public abstract boolean handleResponse(ErResponse resp);
}

Everything seems to be in order, right? Straightforward dependency injection of xmlbinder, except of course, this does not work. Xmlbinder is always null. The problem is that once you take over the job of providing your own objects to be injected, injection doesn't work automagically any more. You'll have to wire up your objects manually too.

Solution:

The provider method has to be changed to:

@Provides
        //XmlBinder has been bound using the application Module
	private ErResponseHandler provideResponseHandlers(XmlBinder xmlbinder) {
		// builds the handlers manually - chain of responsibility pattern
		ErResponseHandler handler = new InactivateAccountResponseHandler(
				new UsageAuthRateChargeResponseHandler());
		handler.setXmlBinder(xmlbinder);
		return handler;
	}

Of course, the BaseResponseHandler class now has to set the xmlbinder accordingly:

public abstract class BaseResponseHandler implements ErResponseHandler {

	protected XmlBinder xmlbinder;	

	public BaseResponseHandler() {
	}
	private ErResponseHandler next;
	public BaseResponseHandler(final ErResponseHandler nextHandler) {
		this.next = nextHandler;
	}
        public void setXmlBinder(final XmlBinder binder) {
		this.xmlbinder = binder;
		if (next != null) {
			next.setXmlBinder(binder);
		}
	}
	public final boolean start(final ErResponse response) {
		boolean handled = this.handleResponse(response);
		if (next != null && !handled) {
			next.start(response);
		}
		return handled;
	}
	public abstract boolean handleResponse(ErResponse resp);
}

Unfortunately, Guice's documentation mentions this only in passing:

Dependencies can be passed in as parameters to the method. The injector will exercise the bindings for each of these before invoking the method

It should really be phrased as

Dependencies must be passed in as parameters to the method. Only then will the injector exercise the bindings for each of these before invoking the method.