Assisted injection

Yesterday I searched the net a little bit. I wanted to utilize dependency injection to create a stateful object. State is evil – you should mumble. Yes it is, but this is not a subject of this post. Let’s see a bit more detail on what I wanted to achieve. All unnecessary stuff will be skipped for brevity.

I had a simple interface, e.g.:

public interface Initialize extends PaymentCapability {
    public Result<Void> initialize();
}

For some reasons I want to put some state in the implementation. In the same time I want to “enable” our partners to kick-out part of or my entire implementation. I ended up in something like this:

public class InitializeImpl implements Initialize {
    public InitializeImpl(Class<?> serviceIfc) {
    }
}

So far so good. I have a constructor and it takes a single argument. If I want to instantiate this I would normally use the new operator (but few years ago :-)) or create a factory. Let’s add one:

public interface InitializeFactory {    
     public Initialize createInitialize(Class<?> serviceIfc);
}

Then I’ll just put some annoying boilerplate code and the factory will be ready to be injected and then eventually ejected :-). Object instantiation is well hidden. Assisted injection addresses exactly the part with the boilerplate code. Guice can provide the implementation of the factory for you! How?

Step 1) You should annotate the implementation of Initialize accordingly:

public class InitializeImpl implements Initialize {
    @Inject
     public InitializeImpl(@Assisted Class<?> serviceIfc){
     }
}

Note the Assisted annotation, it is part of package com.google.inject.assistedinject. Now your build should be eventually red. It is time to move to the next step.

Step 2) Assisted injection is not part of the standard Guice. You should declare a new dependency in your project. Here it is:

compile 'com.google.inject.extensions:guice-assistedinject'

Step 3) Wire the factory in your Guice module:

install(new FactoryModuleBuilder().implement(Initialize.class, InitializeImpl.class).build(InitializeFactory.class));

Step 4) There is no step 4!

The new factory is ready to use and can be injected in the code! So neat! Also note that the constructor of InitializeFactory may be injected additional parameters which are already wired in our modules. Which is very cool.

Assisted injection