When a lot of people discussion static vs. dynamic typing, they are really discussing Java vs. Ruby typing: they simply don’t know any better than to think that Java is representative of static typing. In a similar way, when people hear “dependency injection”, they think Spring. I was one of these people: after getting caught on one too many angle brackets, I was generally put off Spring. The dynamic language features of Groovy made Spring a bit more tolerable within Grails, but I still found it more annoying and obscure than helpful.

For a while, I considered dependency injection to be an informative failure, but something kept nagging at me: the magical variables in Rails are effectively involuntary dependency injection—this pattern is half-jokingly called “dependency ejection” or “dependency secretion”. So there’s something to dependency injection, even if Spring got it wrong.

Then, at JavaOne, I bumped into some of the Google devs, and they pitched me Guice. Some of the pitch points hit home: compile-time type checking; actionable error messages; configured through code; works with immutable classes. However, it still used annotations (which I was busy hating on), and dependency injection was not a popular point with me, so it took me a while to get around to checking Guice out.

I wish I hadn’t waited so long.

Guice does dependency injection as right as I’ve seen, and it makes working within Java and Groovy much nicer. Its simplicity sometimes leads people to underestimate it, however. Recently, I released GuiceJumper, which is my extension to the Guice core library. The code in there demonstrates some of the power of Guice.

For instance, there’s the ExecutorModule. Its primary purpose is to enable classes to ask for an ExecutorService—the core class for concurrency—by specifying the kind of tasks that will be passed to it. The context will provide an appropriately-configured implementation of the ExecutorService, which (if appropriate) is shared throughout the system.

The @Background annotation means the ExecutorService will be appropriate for background task processing. The other options are @Process (CPU-limited processing); @Read (work production and I/O input); and @Write (work consumption and I/O output).

But that’s no big deal: that’s basically a step above rudimentary dependency injection. Slightly cooler: load your application configuration up into your favorite properties file (through, say, Properties.load(Reader)), provide it to the PropertiesModule, and then those properties will be available throughout your system. You can convert them to any primitive type, BigInteger, BigDecimal, Charset, File, URL, URI, or any enum…with actionable errors if the conversion fails. So all those magic constants can now be stored up front in a single configuration step, loaded later, and you will get an early error if they are badly formatted or otherwise bogus. It’s a beautiful thing.

The I18nModule pulls a similar stunt, but uses annotations that look like @Localized("i18n.key") and loads localized values from the ResourceBundle, enabling super-simpler localization of the application and centralization of the messaging.

I’ve got another module to be released which provides all the wiring necessary for the AWS Java SDK objects, but that’s not released to the public yet.

Guice gives you the ability to have a distinct configuration phase to your application, which is entirely under the control of your application, and which need not be at the very beginning. In fact, I have systems that have multiple configuration phases, generating child injectors with new modules as more information becomes available: for instance, my hybrid of Groovy/Guice/Restlet (working title: Restling) creates a new injector for each request. The request injector can provide the request itself, the response, the user, and other request-scoped information.[1] It is worth emphasizing that all of this is configured and controlled by code, which means that you can have precise control over what is going on when, and in the unlikely situation that there is a problem, you can apply your standard debugging tactics. It’s great.

It’s dependency injection without the pain. I love it.

[1] Yes, I am aware that there is a request scope using the servlet plugin for Guice. I find that plugin more magical than helpful, especially given that I can accomplish the same things with nested injectors.