2014-04-27

Guice Tutorial - 06 - Injecting injector

Introduction

Suppose you need a factory which gives you one implementation of interface depends on given parameter. The number of possible implementations is quite big. It could be resolved with factory with injected providers of each implementation, but in Guice we have a better way to achieve this goal...

Main

We could inject Injector to our class. We have a builder factory which could gives us implementation based on parameter:
public class BuilderFactory {
    private Injector injector;

    @Inject
    public BuilderFactory(final Injector injector) {
        this.injector = injector;
    }

    public Builder getBuilder(String param){
    if("first".equals(param)){
        return injector.getInstance(FirstBuilder.class);
        } else if("second".equals(param)){
            return injector.getInstance(SecondBuilder.class);
        } else {
            return injector.getInstance(DefaultBuilder.class);
        }
    }
}
And there are builders:
public interface Builder {}
public class FirstBuilder implements Builder{}
public class SecondBuilder implements Builder{}
public class DefaultBuilder implements Builder{}

First, to test is simply get injector from injector:
@Test
public void shouldInjectInjectorFromInjector(){
    //given
    Injector sut = Guice.createInjector();
    //when
    Injector result = sut.getInstance(Injector.class);
    //then
    assertEquals(sut, result);
}

Now let's get specific builder from our BuilderFactory:
@Test
public void shouldGetFirstBuilderFromFactory(){
    //given
    Injector sut = Guice.createInjector();
    BuilderFactory builderFactory = sut.getInstance(BuilderFactory.class);
    //when
    Builder builder = builderFactory.getBuilder("first");
    //then
    assertTrue(builder instanceof FirstBuilder);
}

@Test
public void shouldGetSecondBuilderFromFactory(){
    //given
    Injector sut = Guice.createInjector();
    BuilderFactory builderFactory = sut.getInstance(BuilderFactory.class);
    //when
    Builder builder = builderFactory.getBuilder("second");
    //then
    assertTrue(builder instanceof SecondBuilder);
}

@Test
public void shouldGetDefaultBuilderFromFactory(){
    //given
    Injector sut = Guice.createInjector();
    BuilderFactory builderFactory = sut.getInstance(BuilderFactory.class);
    //when
    Builder builder = builderFactory.getBuilder("unknown");
    //then
    assertTrue(builder instanceof DefaultBuilder);
}
And every tests pass.

Conclusion

When we have to create factory which gives us many concrete implementation we could inject injector to factory to not inject many providers of this concrete implementations. Source code is available here.

2014-04-20

Guice Tutorial - 05 - Default interface implementation

Introduction

Sometimes we have to define interface and write only one class which implements it, for example we see possibility of extending in future or we want to make our class final to prohibit making subclasses of this type or maybe we want to have one default implementation of interface. This goal could be obtained with Guice.


Interface and class

We have class:
public class PdfReportWriter implements ReportWriter{
    @Override
    public void write() {
        // ...
    }
}
which implements our interface and it is only class which do this. Interface looks so:
@ImplementedBy(PdfReportWriter.class)
public interface ReportWriter {
    void write();
}
By the ImplementedBy annotation we say to Guice that if I ask for object of type ReportWriter than we should by default obtain object of type PdfReportWriter. Let's test it:
@Test
public void shouldGetImplementationOfInterface(){
    //given
    Injector sut = Guice.createInjector();
    //when
    ReportWriter reportWriter = sut.getInstance(ReportWriter.class);
    //then
    assertTrue(reportWriter instanceof PdfReportWriter);
}
And the test passes.


Conclusion

When we have interface which has only one implementation or we want to make this class default implementation for interface than we could use ImplementedBy annotation in Guice. Sources are available here.

2014-04-11

Spock test template for IntelliJ IDEA

Spock tests should have specific structure. I generally use one form of test: with given, when, then and optional where blocks. I also like to have all cases visible, so I add Unroll annotation. I need simple way to generate test in this way.

I am developing using IntelliJ IDEA, so I describe how to configure live template using this IDE. Select File->Settings...->Live Templates. Now add new template group and add new template inside this. Abbreviation set to something meaningful and short, for example spock. As template text use code below:
@spock.lang.Unroll
def "should $END$"(){
    given:
    
    when:
    
    then:
    
    where:
    
}
Set also option "Reformat according to style", apllicable set to groovy and choose expand key.

Now, when you type spock and click expand key (in my case it is Tab) in editor, then spock will be replaced with template and coursor will be set after space in test method name.

2014-04-06

Guice Tutorial - 04 - Default providers and scopes

Introduction

This time I want to show you, what Guice will do, when we ask for provider for class, but we have not defined any provider and when we obtain new objects from injector and when already used objects. All sources are available here.

Default providers

First, let's create a small class:
public class UserSession {}
We do not define any profider, but when we ask for provider, than provider will be given to us.
@Test
public void shouldGetEachTimeNewSessionFromProvider(){
    //given
    Injector injector = Guice.createInjector();
    Provider<UserSession> sut = injector.getProvider(UserSession.class);
    //when
    UserSession userSession = sut.get();
    //then
    assertNotNull(userSession);
}

Scopes

For each request to injector or default provider we obtain new object. This is default scope of dependencies maintained by Guice. For example:
@Test
public void shouldGetEachTimeNewSession(){
    //given
    Injector sut = Guice.createInjector();
    //when
    UserSession userSession1 = sut.getInstance(UserSession.class);
    UserSession userSession2 = sut.getInstance(UserSession.class);
    //then
    assertNotEquals(userSession1, userSession2);
}
But suppose we should have only one instance of class, for example generator.
@Singleton
public class SequenceGenerator {
    private int counter = 0;

    public int next(){
        return counter++;
    }
}
The Singleton annotation tells Guice that we want only one instance of this class, so if we get instance of this class from injector or default provider, than we obtain the same instance.
@Test
public void shouldGetTheSameSequenceGeneratorEachTime(){
    //given
    Injector injector = Guice.createInjector();
    //when
    SequenceGenerator sequenceGenerator1 = injector.getInstance(SequenceGenerator.class);
    SequenceGenerator sequenceGenerator2 = injector.getInstance(SequenceGenerator.class);
    //then
    assertEquals(sequenceGenerator1, sequenceGenerator2);
}
@Test
public void shouldGetTheSameSequenceGeneratorEachTimeFromProvider(){
    //given
    Injector injector = Guice.createInjector();
    Provider<SequenceGenerator> sut = injector.getProvider(SequenceGenerator.class);
    //when
    SequenceGenerator sequenceGenerator1 = sut.get();
    SequenceGenerator sequenceGenerator2 = sut.get();
    //then
    assertEquals(sequenceGenerator1, sequenceGenerator2);
}
Of course dependency is singleton in Guice context, so you could create new object of this class outside from Guice and no one could stop you.

Conclusion

Guice generates for us default providers in default scope. Providers give us new objects for each request to their. We could also change scope of class to Singleton and then for each request we obtain the same object. 

2014-04-02

Guice Tutorial - 03 - Providers

Introduction

Dependencies injected by Guice are generally created using annotated constructor. But sometimes you need a generator of specific class objects or you have to initialize your class before using it. These goals you can meet using providers. First, suppose you have ReportController, which stores given message with actual date in some place (database, file).


Injecting Provider

If you want to write good unit tests, you should protect yourself against changing date, so you can inject a kind of date generator - Provider of Date.
public class DateProviderTest {
    @Test
    public void shouldGetAnotherTimeForEachGet() throws InterruptedException {
        // given
        Injector injector = Guice.createInjector();
        Provider<Date> sut = injector.getProvider(Date.class);
        // when
        Date firstDate = sut.get();
        Thread.sleep(1);
        Date secondDate = sut.get();
        // then
        assertNotNull(firstDate);
        assertNotNull(secondDate);
        assertNotEquals(firstDate.getTime(), secondDate.getTime());
    }
}
In unit tests for classes, which use this provider you only need to mock Provider interface and return fixed date on each call.


Injecting via provider

Sometimes your objects should be additionally prepared before using, for example you have to call initialize method. It also could be done in described above way or you could use ProvidedBy annotation and explicit define Provider for your class. First, let's define class which should be initialized before using:
@ProvidedBy(ReportSessionFactory.class)
public class ReportSession {
    private boolean initialized;

    public ReportSession() {}

    public void init() {
        this.initialized = true;
    }

    public boolean isInitialized() {
        return initialized;
    }
    public boolean report(final String reportMessage, final Date date) {
        if(!initialized){
            return false;
        }
        // ...
        return true;
    }
}
ProvidesBy points to class which implements Provider interface:
public class ReportSessionFactory implements Provider<ReportSession> {
    @Override
    public ReportSession get() {
        ReportSession reportSession = new ReportSession();
        reportSession.init();
        return reportSession;
    }
}
Now when we will inject object of class ReportSession it will be given to us from provider and already initialized:
public class ReportSessionProviderTest {
    @Test
    public void shouldInitReportSession() {
        // given
        Injector injector = Guice.createInjector();
        ReportSession sut = injector.getInstance(ReportSession.class);
        // when
        boolean result = sut.isInitialized();
        // then
        assertTrue(result);
    }
}

Conclusion

When you need to inject a generator of runtime dependent objects or have to call method of dependency immediately after constructor, Guice providers are the best options for you. Sources are available here.