AbstractModule.bindConstant(), @Inject and @Named in Google Guice

I’ve recently come across the bindConstant() method of com.google.inject.AbstractModule. I had a vague idea of its use and value, and decided to google it. I was looking for some code examples and got really surprised when it took me quite a while until I was finally able to find one at Guice: Difference between Binder#bindConstant() and Binder#bind() … toInstance. It wasn’t complete though, but it gave me a hint on the further steps.

The idea behind

AbstractModule.bindConstant()

is to bind a value to a instance or class field. Use Guice’s

@Inject

and

@Named

annotations together to let the DI framework know about the place (via @Inject) and its name (or rather qualifier, via @Named) to inject a value to.

package pl.jaceklaskowski.guice;

import com.google.inject.Inject;
import com.google.inject.name.Named;

public class App
{
    @Inject @Named("port") public int port;

    public int getPort() {
        return port;
    }

    public static void main( String[] args )
    {
        System.out.println( "Hello World at " + new App().getPort() + "!" );
    }
}

With these annotations you effectively mark the field to be managed by Guice. That’s, say, “a client’s side”.

“The provider’s side” requires a configuration – a Guice module – to instruct it about the value to bind to the field. Below you can find a complete test with

setUp()

method and the module itself (as anonymous class).

package pl.jaceklaskowski.guice;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class AppTest {
    private static final int PORT = 8080;

    Injector injector;

    @Before
    public void setUp() throws Exception {
        injector = Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
                bindConstant().annotatedWith(Names.named("port")).to(PORT);
            }
        });
    }

    @After
    public void tearDown() throws Exception {
        injector = null;
    }

    @Test
    public void testGetPort() throws Exception {
        App app = injector.getInstance(App.class);
        assertEquals(PORT, app.getPort());
    }
}

A complete Maven-based project is in my github account as the guice-bindconstant module in guice-samples.

Be Sociable, Share!
This entry was posted in Frameworks.

2 Responses to AbstractModule.bindConstant(), @Inject and @Named in Google Guice

  1. Maciej Biłas says:

    Jacek, what you showed here is plain field dependency injection[1]. You can obtain the very same thing configuring the module with bind(Integer.TYPE).annotatedWith(Names.named(“port”)).toInstance(8080);

    From what I understand Guice documentation automatic type conversion is what is important (an added value compared plain bind()) about constant binding.

    Try doing: bindConstant().annotatedWith(Names.named(“port”)).to(“8080”);
    Mind that the port number here is a string. If you now inject it to a int-type field it Guice will perform the conversion automatically for you.

    Feel free to correct me if I’m wrong.

    [1] http://code.google.com/p/google-guice/wiki/Injections#Field_Injection

    • Jacek Laskowski says:

      Thanks Maciej. I’d read about it before posting, but didn’t think it was important that much. Now I think otherwise. Thanks for pointing it out. Now, as we’re at it, I wonder how much of support Guice provides for the type conversion.

Leave a Reply

%d bloggers like this: