This blog has moved to Medium

Subscribe via email


1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Posts tagged ‘guice’

MapBinder basics in Guice

Another less known feature in Google Guice is map binders. I haven’t seen a good basic map binder tutorial, so I wanted to share the little I learned about it (it is covered in the documentation, but it’s not necessarily the best intro material). Basically, is a way to collect bindings from several models into one central map. The idiom is having each module add bindings from its “knowledge domain”, and providing the entire collection as one unified map.

class SomeModule {
  protected void configure() {
     // Bind the value "Eve" to the key "Adam"
     MapBinder.newMapBinder(binder(), String.class, String.class)
       .addBinding("Adam").toInstance("Eve");
  }
}
 
class AnotherModule {
  protected void configure() {
     // Bind the value "Abel" to the key "Kane"
     MapBinder.newMapBinder(binder(), String.class, String.class)
       .addBinding("Kane").toInstance("Abel");
  }
}
 
class NeedsMap {
  @Inject
  NeedsMap(Map<String, String> biblicalNames) {
    // gets a map of all values bound in the relevant modules
  }
}
 
main() {
  NeedsMap needsMap = Guice.createInjector(new SomeModule(), new AnotherModule()).getInstance(NeedsMap.class);
}

Of course, the map can be specified using any types, not just String, and doesn’t have to bind to a specific instance, but can bind to a class. To use this, remember to depend on the proper Guice Extension (Maven guice-multibindings). The code is available on Github. Check out this questions for “when is this actually useful?

Assisted Injection in Guice

Dependency Injection* is a common and useful design pattern. It moves the responsibility for creating a class’ dependencies out to its instantiater, thus allowing for easier customization and testability. A useful DI flavor is to create constructors that directly depend on a set of components, and having the caller provide these arguments upon construction. A DI framework (e.g. Guice for Java or StructureMap for .Net) will save you the trouble of having to pass along these dependencies directly, and instead turn your object construction into beautiful magic such as:

// In real code you will usually use a Provider instead of an Injector
Foo foo = injector.getInstance(Foo.class)

Instead of

Foo foo = new Foo(bar, baz, boom, .......)

This technique is easiest when a class only depends on services and other general classes.
The problem starts when a class just has to have a real, “non standard” paramater passed upon construction (e.g. a TestRunner class that accepts a numberOfRetries parameter). In simple cases, you might just forgoe the use of your DI framework for the simplicity of writing

new TestRunner(3)

But what do you do when your class has both a lot of dependencies, and a parameter you just have to pass during construction time?
One option is using a setter to pass along the actual argument, instead of requiring it during construction. While this can work, it has the shortcomings of not being able to store this value in a final field, and not being able to use it during the constructor, often forcing
you to create a separate init() method.

Another possible option is creating a separate factory class. This class will contain all the “easy” dependencies of the original class, and not the parameter. You can construct such a class with the DI framework directly, and then pass the parameter to its build() method. This skips over the disadvantages of the setter approach, and makes the calling code rather clean, but has the small problem of a code duplication between the factory and the class being built – this is especially apparent if the target class has a huge number of parameters – the factory class is essentially boilerplate “stupid” code.

Introducing … Assisted Injection (applause)

Assisted injection is a Guice concept that elegantly solves the parametric construction problem. It is actually documented quite well, so I’ll just describe it briefly – you only need to declare a factory interface, annotate the relevant constructor parameters with @Assisted, tell guice the name of the builder interface for a given class and you’re home free – Guice creates the boilerplate factory class described above behind the scenes.

Foo foo = injector.getInstance(FooBuilder.class).build(3);

* For the purpose of this post I tream Dependency Injection and Inversion of Control as the same pattern, although they are technically two related yet different patterns.