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.