Showing posts with label Dependency Injection. Show all posts
Showing posts with label Dependency Injection. Show all posts

2015-12-08

Spring autowire with qualifiers

Introduction

Autowired is great annotation, which by default inject beans by type to annotated element (constructor, setter or field). But how to use it, when there is more than one bean of requested type.

Autowired with one bean

Suppose we will work with small interface:

interface IHeaderPrinter {
    String printHeader(String header)
}

When we have only one bean implementing IHeaderPrinter:

@Component
class HtmlHeaderPrinter implements IHeaderPrinter{
    @Override
    String printHeader(String header) {
        return "<h1>$header</h1>"
    }
}

then everything works great and test passes.

@Autowired
IHeaderPrinter headerPrinter

@Test
void shouldPrintHtmlHeader() {
    assert headerPrinter.printHeader('myTitle') == '<h1>myTitle</h1>'
}

Two implementations

But what will happen, if we add another implementation of IHeaderPrinter, e. g. MarkdownHeaderPrinter?

@Component
class MarkdownHeaderPrinter implements IHeaderPrinter {
    @Override
    String printHeader(String header) {
        return "# $header"
    }
}

Now out test with fail with exception:

Error creating bean with name 'com.blogspot.przybyszd.spring.autowire.SpringAutowireWithQualifiersApplicationTests': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.blogspot.przybyszd.spring.autowire.IHeaderPrinter com.blogspot.przybyszd.spring.autowire.SpringAutowireWithQualifiersApplicationTests.headerPrinter; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.blogspot.przybyszd.spring.autowire.IHeaderPrinter] is defined: expected single matching bean but found 2: markdownHeaderPrinter,htmlHeaderPrinter

We have to decide which implementation we want to use in our test, so ...

Two implementations with Qualifier

Each bean is registered with name equal its class. For example HtmlHeaderPrinter is named htmlHeaderPrinter. The name is also its qualifier. We have to tell Autowired, that it should inject htmlHeaderPrinter:

@Autowired
@Qualifier('htmlHeaderPrinter')
IHeaderPrinter headerPrinter

Now our test passes again.

Two implementations qualified by field name

If field is names like implementing class (for example htmlHeaderPrinter), then this class implementation will be injected:

@Autowired
IHeaderPrinter htmlHeaderPrinter

And test passes:

@Test
void shouldPrintHtmlHeader() {
    assert htmlHeaderPrinter.printHeader('myTitle') == '<h1>myTitle</h1>'
}

Thanks to @marcinjasion.

Two implementation with Primary

We often have one implementation which we almost always want to inject, so do we still have to put Qualifier with its name wherever we want to use it? No.

We could mark one implementation as Primary and this bean will be wired by default (unless we explicit give another Qualifier to use injection point):

@Component
@Primary
class HtmlHeaderPrinter implements IHeaderPrinter{
    // ...
}
@Autowired
IHeaderPrinter headerPrinter

Summary

Autowired annotation allows us to inject dependencies to beans. It works great without additional configuration, when each bean could be uniquely find by type. When we have more than one bean, that could be injected, we have to use Qualifier or Primary annotation to help it find desired implementation.

Source code is available here.

2014-05-17

Guice Tutorial - 09 - Providers in modules

Introduction

Module in Guice is not only a place where binding are defined. It also could have definition of many providers inside.


Provides

Suppose we have quiz class which has to be initialized before usage by call of method init.
public class Quiz {
    private boolean initialized = false;

    public boolean initialized(){
        return initialized;
    }

    public void init(){
        initialized = true;
    }
}
Provider is quite simple, because it only creates Quiz object and call method init, so we define it inside module.
public class QuizModule extends AbstractModule {
    @Override
    protected void configure() {}

    @Provides
    private Quiz getinitializedQuiz(){
        Quiz quiz = new Quiz();
        quiz.init();
        return quiz;
    }
}
Provides annotation tells Guice that annotated method is provider for its return type. Provider could be defined in this manner only in module.
Let's test it:
@Test
public void shouldClassInstanceFromProvider(){
    //given
    Injector sut = Guice.createInjector(new QuizModule());
    //when
    Quiz quiz = sut.getInstance(Quiz.class);
    //then
    assertTrue(quiz.initialized());
}

Conclusion

If you have to define provider, but you do not want to have separete provider class, than you could create method which acts like provider in your module. Sources are available here.

2014-05-01

Guice Tutorial - 07 - Module

Introduction

So far, we was using only annotations and creating injector without giving any parameters. It could be possible, because we was using classes defined by us or having no-arg constructor. But sometimes we have to use classes from external library, which do not meet these conditions. With the help comes to us Module.

Module

The module is an interface which has only one method - configure, where bindings could be defined. Binding is a form, which tells injector how to obtain instance of class that we ask for. It looks like this: bind(class).toSth(...). The best way to have defined bind method in your module is extend AbstractModule class.
public class MyModule extends AbstractModule{
    @Override
    protected void configure() {
        //...
    }
}
Module is the main definition for injector and when something is undefined then it also use bindings defined via annotations. Important is that module always overrides annotations, for example when class has annotations and module defines binding for it, then module binding is used.

Binding to constructor

First binding tells how to obtain class using constructor and there is method toConstructor where you could pass a constructor:
try {
    bind(FirstClass.class).toConstructor(FirstClass.class.getConstructor(Dependency.class));
} catch(NoSuchMethodException e) {
    // But i know it exists
    e.printStackTrace();
}
FirstClass class (and almost all class used in examples) looks like this:
public class FirstClass {
    private Dependency dependency;

    public FirstClass(final Dependency dependency) {
        this.dependency = dependency;
    }
}
It is not so easy to define constructor in this way so if I could I use Inject annotation, which means the same.
public class SecondClass {
    private Dependency dependency;

    @Inject
    public SecondClass(final Dependency dependency) {
        this.dependency = dependency;
    }
}

Binding to provider

We are using Provider to prepare class and module changes nothing, but we could replace ProvidedBy annotation in class with toProvider method in module:
bind(ThirdClass.class).toProvider(ThirdClassProvider.class);

Binding to instance

Of course, you could create one instance of class and want to pass it to every class, which could use it. We bind it using toInstance.
bind(FourthClass.class).toInstance(new FourthClass(new Dependency()));

Binding to concrete implementation

When we want to inject concrete implementation for interface or abstract class we have been using ImplementedBy annotation. In module we could simply use to and tell which class we want to bind to it. Of course, we have to define how to obtain this class (in module or via annotations).
bind(SomeClass.class).to(FifthClass.class);

Using scope

We could define that we want the class to be the singleton via annotation Singleton, so in module we should have this possibility too. And we have. We could tell in which scope class should be using method in at the end of each binding. For example:
try {
    bind(SixthClass.class).toConstructor(SixthClass.class.getConstructor(Dependency.class)).in(Singleton.class);
} catch(NoSuchMethodException e) {
    e.printStackTrace();
}

Conclusion

Annotations and module could be used to describe how injector should create instances of classes that we ask for. But annotations could be placed only on our classes, while module could describe creation for each class and is more important for Injector than annotations. 
All sources are available here.

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.

2014-03-23

Guice Tutorial - 02 - Injection points

Introduction

There are three points, where you can inject your dependecies. In previous part of this tutorial I have use injection to costructor. Available are also injections to setters or directly to fields. Today our domain will be order processing.

Main

First some classes, which will be our dependecies:
public class Order {
    private final String item;
    private final int amount;

    public Order(final String item, final int amount) {
        this.item = item;
        this.amount = amount;
    }

    public String getItem() {
        return item;
    }

    public int getAmount() {
        return amount;
    }
}

public class OrderProcessor {
    public void process(final Order order) {
        // ...
    }
}

public class OrderDao {
    public void save(final Order order) {
        // ...
    }
}

class OrderValidator {
    public void validate(final Order order) {
        // ...
    }
}

Controller which has all these dependecies is here:
public class OrderController {
    private final OrderDao orderDao;

    private OrderProcessor orderProcessor;

    @Inject
    private OrderValidator orderValidator;

    @Inject
    public OrderController(final OrderDao orderDao) {
        this.orderDao = orderDao;
    }

    @Inject
    public void setOrderProcessor(final OrderProcessor orderProcessor) {
        this.orderProcessor = orderProcessor;
    }

    public void invokeProcessing(final Order order) {
        orderValidator.validate(order);
        orderDao.save(order);
        orderProcessor.process(order);
    }
}

As you can see, the Inject annotation is set on constructor of whole class, setter of OrderDao and on OrderValidator field. Injecting to constructor is the best option in my opinion, because all needed dependecies should be inject, when class is created.
Setter injection sometimes is helpful, for example when you need to inject something later using injectMember (it will be cover in one of next parts).
Field injecting is often a bad idea, because during testing this field should be protected or default (or public, but this is the worst idea) to mock this dependency. Of course you can use refletion, but reflection API is not easy to use. But you have this opportunity to inject field.

Testing

One simple test to prove that all this injection points works and there are not NullPointerExceptions.
public class OrderControllerIT {
    @Test
    public void shouldInjectAllDependency() {
        //given
        Injector injector = Guice.createInjector();
        Order order = new Order("apple", 10);
        //when
        OrderController sut = injector.getInstance(OrderController.class);
        //then
        sut.invokeProcessing(order);
    }
}


Conclusion

You could inject dependecies in three placess in classes, but you almost always should use constructor injector. Injecting to setters should be hardly ever used. Field injecting is available, but should not be used.
All sources are available here.

2014-03-16

Guice Tutorial - 01 - The simplest injection

Introduction

Guice is very powerful and simple dependency injection library from Google. There is no need to create xml configuration or have container to use it. Moreover, it gives us objects already casted to desired types. In this post I will show how to start working with guice and make the simplest injection. In this case, domain will be adding persons. All sources are available here.


Main

First, we have to add maven dependency to guice and optionally to javax.inject:
<dependency>
    <groupId>com.google.inject</groupId>
    <artifactId>guice</artifactId>
    <version>3.0</version>
</dependency>
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
Guice has own annotations to describe injections, but I like to use javax.inject annotation, which could also be used with Guice and are part of JavaEE.


Person is described by given class:
public class Person {
    private String firstName;
    private String lastName;
    private Integer age;

    public Person(final String firstName, final String lastName, 
                  final Integer age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    //...
}
We also need PersonDao and PersonValidator:
public class PersonDao {
    public void persist(final Person user) {
        // ...
    }
}
public class PersonValidator {
    void validate(final Person user) throws PersonValidationException {
        // ...
    }
}
Now we have all dependencies so let's create controller, which will use this classes:
public class PersonController {
    private final PersonValidator userValidator;
    private final PersonDao userDao;

    @Inject
    public PersonController(final PersonValidator userValidator, 
                            final PersonDao userDao){
        this.userValidator = userValidator;
        this.userDao = userDao;
    }

    public void add(final Person user) throws PersonValidationException{
        userValidator.validate(user);
        userDao.persist(user);
    }
}
The magic is in annotation Inject. In Guice, when we want to use class with not default, no argument constructor, we have to add this annotation to one of constructor.


Testing

It is time to test it. I will use JUnit.
@Test
public void shouldGetPersonControllerFromInjectorAndPersistPerson() {
    //given
    Injector injector = Guice.createInjector();
    Person user = new Person("John", "Smith", 25);
    //when
    PersonController userController = injector.getInstance(PersonController.class);
    //then
    userController.add(user);
}
All classes could be obtained from Guice via Injector. Injector collects all classes in classpath and allows to get their instances if they have default constructors or constructors annotated with Inject (from Guice or javax).
Method add of userController pass without exception so Guice has injected PersonDao and Person Validator classes. 


Conclusion

Guice is very simple and in basic cases we need only to use Inject annotation on class with dependecies. We only have to call getInstance and tell Guice which class (or interface) we want.