Dependency Injection in Java is easy - Part 2 - Google Guice
Tags: java, programming, tutorial, code
Published: 2020-08-09 21:13:29

---
title: Dependency Injection in Java is easy - Part 2 - Google Guice
published: true
description: This is a series of posts simplifying and exemplifying Dependency Injection in Java.
tags: ["java", "programming", "tutorial", "code"]
cover_image: https://source.unsplash.com/ieic5Tq8YMk
series: Dependency Injection in Java is easy
---

## Part 2 - Google Guice

This post is part of a multiple-part tutorial. As the heading suggests, this part will focus on Dependency Injection using [Google Guice](https://github.com/google/guice/wiki).

You can check out the code for this tutorial part in [Github][0].

### Background

It's advised to start with [Part 1 - A Design Pattern][1], which this part requires. The next [Part 3 - Spring Context][3] doesn't require this one.

If you have read [Part 2][2], you can skip to the [incorporating guice section](#incorporating-google-guice).

### Dependency Injection Frameworks

DI Frameworks concept is pretty straightforward; the framework creates and manages our dependencies for us.
On one end, we provide the framework instructions for creating our dependencies; on the other, we ask the framework for instances of the dependencies.

Comparing multiple frameworks, we'll notice different features, component names, default behaviors, and probably different implementations under the hood. But the gist will be the same: a container that holds our dependencies. Let's explore some similarities between various frameworks:

- [Spring's Autowired](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-autowired-annotation) and [Guice's Inject](https://github.com/google/guice/wiki/GettingStarted#inject-constructor), both mark a dependency for injection.

- [Spring's Bean](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-java-bean-annotation) and [Guice's Provides](https://github.com/google/guice/wiki/ProvidesMethods), both incorporate logic for creating a dependency.

Not a believer yet :grey_question: Alright, let's throw `C#` in the mix :grey_exclamation:

- [Spring's Configuration](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-annotation-config), [Guice's Modules](https://github.com/google/guice/wiki/GettingStarted#guice-modules), and [Autofac's Modules](https://autofaccn.readthedocs.io/en/latest/configuration/modules.html), can be used to configure dependencies.

- [Guice's Binding](https://github.com/google/guice/wiki/Bindings) and [Autofac's Registration](https://autofaccn.readthedocs.io/en/latest/register/registration.html) are used to configure dependencies with the framework's DSL.

We can go on. But the point is made.</br>
:sunglasses:

Under the hood, DI Frameworks builds factories providing dependencies based on multiple criteria, such as type and name.

At the base level, there are three typical scopes for dependencies living in a DI Framework container:

- *Eager Singleton*: **one instance** of the dependency will be created **immediately upon the framework's instantiation**; the same instance will be provided for every request.

- *Lazy Singleton*: **one instance** of the dependency will be created **only when requested**. Upon its instantiation, the same instance will be provided for every request.

- *Non-Singleton*: **A new instance** of the dependency will be provided for every request.

There are more scopes, but these are the three most commonly used. Some frameworks offer different scopes than others. Such as *per session*, *per request*, *per dependency*, etc.

### Example App

Heads up: The example app next is based on [Part 1 - A Design Pattern][1]; you can skip to the [incorporating guice section](#incorporating-google-guice).

### Mail Collector App

Let's build an app pulling emails from both *Gmail* and *Microsoft* leveraging the *Dependency Injection* pattern with *Google Guice*.

#### Contracts

An *Enum* called `MailSource` for categorizing the email source:

```java
public enum MailSource {
  GMAIL,
  MICROSOFT;
}
```

An abstract class `Mail` for contracting mail objects.

```java
public abstract class Mail {
  public abstract String from();

  public abstract String subject();

  public abstract MailSource source();

  @Override
  public String toString() {
    return String.format("Got mail by %s, from %s, with the subject %s", source(), from(), subject());
  }
}
```

An interface for contracting services responsible for pulling Mail from suppliers, the `MailService`.

```java
public interface MailService {
  List<Mail> getMail();
}
```

And last, an interface for contracting an engine responsible for collecting Mail from multiple services, the `MailEngine`.

```java
public interface MailEngine {
  List<Mail> getAllMail();
}
```

#### Implementations

##### Mail

The concrete `Mail` implementations were designed with a *builder pattern* for convenience and immutability.</br>
The *Gmail* `Mail` implementation, `GmailImpl`:

```java
public final class GmailImpl extends Mail {
  private final String setFrom;
  private final String setSubject;

  private GmailImpl(final String from, final String subject) {
    setFrom = from;
    setSubject = subject;
  }

  @Override
  public String from() {
    return setFrom;
  }

  @Override
  public String subject() {
    return setSubject;
  }

  @Override
  public MailSource source() {
    return MailSource.GMAIL;
  }

  public static GmailImpl.Builder builder() {
    return new GmailImpl.Builder();
  }

  public static final class Builder {
    private String prepFrom;
    private String prepSubject;

    public Builder from(final String setFrom) {
      prepFrom = setFrom;
      return this;
    }

    public Builder subject(final String setSubject) {
      prepSubject = setSubject;
      return this;
    }

    public GmailImpl build() {
      requireNonNull(emptyToNull(prepFrom), "from cannot be empty or null");
      requireNonNull(emptyToNull(prepSubject), "subject cannot be empty or null");

      return new GmailImpl(prepFrom, prepSubject);
    }
  }
}
```

The *Micsorosft* `Mail` implementation, `MicrosoftImpl`:

```java
public final class MicrosoftImpl extends Mail {
  private final String setFrom;
  private final String setSubject;

  private MicrosoftImpl(final String from, final String subject) {
    setFrom = from;
    setSubject = subject;
  }

  @Override
  public String from() {
    return setFrom;
  }

  @Override
  public String subject() {
    return setSubject;
  }

  @Override
  public MailSource source() {
    return MailSource.MICROSOFT;
  }

  public static MicrosoftImpl.Builder builder() {
    return new MicrosoftImpl.Builder();
  }

  public static final class Builder {
    private String prepFrom;
    private String prepSubject;

    public Builder from(final String setFrom) {
      prepFrom = setFrom;
      return this;
    }

    public Builder subject(final String setSubject) {
      prepSubject = setSubject;
      return this;
    }

    public MicrosoftImpl build() {
      requireNonNull(emptyToNull(prepFrom), "from cannot be empty or null");
      requireNonNull(emptyToNull(prepSubject), "subject cannot be empty or null");

      return new MicrosoftImpl(prepFrom, prepSubject);
    }
  }
}
```

##### Mail Services

The *Gmail* `MailService` implementation:

```java
public final class GmailService implements MailService {
  @Override
  public List<Mail> getMail() {
    //This is where the actual Gmail API access goes.
    //We'll fake a couple of emails instead.
    var firstFakeMail =
        GmailImpl.builder()
            .from("a.cool.friend@gmail.com")
            .subject("wanna get together and write some code?")
            .build();

    var secondFakeMail =
        GmailImpl.builder()
            .from("an.annoying.salesman@some.company.com")
            .subject("wanna buy some stuff?")
            .build();

    return List.of(firstFakeMail, secondFakeMail);
  }
}
```

The *Microsoft* `MailService` implementation:

```java
public final class MicrosoftService implements MailService {
  @Override
  public List<Mail> getMail() {
    //This is where the actual Microsoft API access goes.
    //We'll fake a couple of emails instead.
    var firstFakeMail =
        MicrosoftImpl.builder()
            .from("my.boss@work.info")
            .subject("stop writing tutorials and get back to work!")
            .build();

    var secondFakeMail =
        MicrosoftImpl.builder()
            .from("next.door.neighbor@kibutz.org")
            .subject("do you have philips screwdriver?")
            .build();

    return List.of(firstFakeMail, secondFakeMail);
  }
}
```

##### Mail Engine

```java
public final class RobustMailEngine implements MailEngine {
  private final Set<MailService> mailServices;

  public RobustMailEngine(final Set<MailService> setMailSerices) {
    mailServices = setMailSerices;
  }

  @Override
  public List<Mail> getAllMail() {
    return mailServices.stream().map(MailService::getMail).flatMap(List::stream).collect(toList());
  }
}
```

#### The Main App

This is the app itself, the `MailCollectorApp`:

```java
public final class MailCollectorApp {
  private MailEngine engine;

  public MailCollectorApp(final MailEngine setEngine) {
    engine = setEngine;
  }

  public String getMail() {
    var ret = "No mail found.";
    if (!engine.getAllMail().isEmpty()) {
      ret = Joiner.on(System.lineSeparator()).join(engine.getAllMail());
    }
    return ret;
  }

  public static void main(final String... args) {
    var gmailService = new GmailService();
    var microsoftService = new MicrosoftService();

    var engine = new RobustMailEngine(Set.of(gmailService, microsoftService));

    var app = new MailCollectorApp(engine);

    System.out.println(app.getMail());
  }
}
```

Executing the *main method* will print:

```text
Got Mail by GMAIL, from a.cool.friend@gmail.com, with the subject wanna get together and write some code?
Got Mail by GMAIL, from an.annoying.salesman@some.company.com, with the subject wanna buy some stuff?
Got Mail by MICROSOFT, from my.boss@work.info, with the subject stop writing tutorials and get back to work!
Got Mail by MICROSOFT, from next.door.neighbor@kibutz.org, with the subject do you have a star screwdriver?
```

This application uses the *dependency injection design pattern*. The dependencies are currently controlled by the `main` method, so it should be easy to incorporate [Google Guice](https://github.com/google/guice/wiki).

### Incorporating Spring Context

#### Include maven dependency

First, let's add this to our *pom.xml* in the *dependencies* section:</br>
Note that this version was the latest when this tutorial was written.

```xml
<dependency>
  <groupId>com.google.inject</groupId>
  <artifactId>guice</artifactId>
  <version>4.2.3</version>
</dependency>
```

#### Mark Inject

We need to tell *Guice* about the dependencies we want to be injected. Let's do this for the concrete engine class:

```java
public final class RobustMailEngine implements MailEngine {
  private final Set<MailService> mailServices;

  @Inject
  public RobustMailEngine(final Set<MailService> setMailSerices) {
    mailServices = setMailSerices;
  }

  @Override
  public List<Mail> getAllMail() {
    return mailServices.stream().map(MailService::getMail).flatMap(List::stream).collect(toList());
  }
}
```

And for the app class:

```java
public final class MailCollectorApp {
  private MailEngine engine;

  @Inject
  public MailCollectorApp(final MailEngine setEngine) {
    engine = setEngine;
  }

  public String getMail() {
    var ret = "No mail found.";
    if (!engine.getAllMail().isEmpty()) {
      ret = Joiner.on(System.lineSeparator()).join(engine.getAllMail());
    }
    return ret;
  }

  //...
}
```

Now, we need to instruct *Guice* on providing those dependencies.

#### Provide Dependencies

Let's create a *Guice Module* for configuring the bindings; multiple approaches exist to achieve that. For instance, using [Guice's Provides Methods](https://github.com/google/guice/wiki/ProvidesMethods):

```java
public final class DIModule extends AbstractModule {
  @Provides
  static Set<MailService> getServices() {
    return Set.of(new GmailService(), new MicrosoftService());
  }

  @Provides
  @Singleton
  static MailEngine getEngine(final Set<MailService> services) {
    return new RobustMailEngine(services);
  }
}
```

Another approach to configuring *Guice* bindings is using [Guice's bind DSL](https://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/Binder.html):

```java
public final class DIModule extends AbstractModule {
  @Override
  public void configure() {
    var listBinder = newSetBinder(binder(), MailService.class);
    listBinder.addBinding().toInstance(new GmailService());
    listBinder.addBinding().toInstance(new MicrosoftService());

    bind(MailEngine.class).to(RobustMailEngine.class).in(Scopes.SINGLETON);
  }
}
```

Both options will produce the same dependencies.

*Guice*'s default [scope](https://github.com/google/guice/wiki/Scopes) is *Non-Singleton*. This means that the *Set* of *GmailService* and *MicrosoftService* will be created as new instances for every object that needs them.

On the other end, the *RobustMailEngine* will be bound as a *Singelton*.
Based on [Guice's docs](https://github.com/google/guice/wiki/Scopes#eager-singletons), that means that in *Production stage* it will be an *Eager Singleton*, and in *Development stage* it will be a *Lazy Singleton*.
Either way, it's going to be a *Singleton*, meaning our app will have only one instance of *RobustMailEngine*.

The default stage for *Guice* is *Development stage*, so we can expect a *Lazy Singleton*.

Note, *RobustMailEngine* is a dependency; it will be injected to whoever requests it, but as we configured earlier, it also needs dependencies for itself (the *Set* of *MailService*).</br>
> *Guice* will catch that and inject the set of mail services while instantiating the engine.

#### Update the app to use Guice

Getting back to our app. Let's update it to work with *Guice*:

```java
public final class MailCollectorApp {
  private MailEngine engine;

  @Inject
  public MailCollectorApp(final MailEngine setEngine) {
    engine = setEngine;
  }

  public String getMail() {
    var ret = "No mail found.";
    if (!engine.getAllMail().isEmpty()) {
      ret = Joiner.on(System.lineSeparator()).join(engine.getAllMail());
    }
    return ret;
  }

  public static void main(final String... args) {
    var injector = Guice.createInjector(new DIModule());

    var app = injector.getInstance(MailCollectorApp.class);

    System.out.println(app.getMail());
  }
}
```

Let's analyze what's going on here...

Running the *main* method will create a *Guice's injector*, which is the context for all dependencies. As we create it with an instance of our *DIModule* class, the injector's context will have the following dependencies configured in it:

- A *Set* of two *MailService* objects (*GmailService* and *Microsoft Service*).
- A *Singleton* instance of *MailEngine* (*RobustMailEngine*).

As stated, in the *Development stage* the *MainEngine* is a *Lazy Singleton*, plus, we configured the *Set* of *MailService* as *Non-Singleton*. That means that there's nothing instantiated in the injector's context at this point.

The next step, asking the injector for an instance of *MailCollectorApp*, will accomplish the following:

- *Guice* will pick up the constructor in *MailCollectorApp*, as it's the only constructor.

- As the constructor is marked with *@Inject*, *Guice* will look in its context for a dependency of type *MailEngine*.

- It will find the *RobustMailEngine* configured, which is a *Lazy Singleton*.

- While trying to instantiate it, it will pick up its constructor, which is also marked with *@Inject*. And look for a suitable dependency with the type *Set* of *MailService*.

- It will find the *Set* of *GoogleService* and *MicrosoftService*, which is a *Non-Singleton*.

After preparing the *dependency graph*, *Guice* will:

- Create the set after instantiating both *GmailService* and *MicrosoftService*.

- Instantiate the *RobustMailEngine* injecting the *Set*.

- Instantiate the *MailCollectorApp* injecting the *RobustMailEngine*.

We then get our instance *MailCollectorApp* with everything we need, from which we invoke getMail to get all our Mail.

That's it, *Guice* in a nutshell.</br>
:satisfied:

Now, Let's test the code.

### Unit Tests

I will start by saying that when it comes to unit tests, if possible, I always prefer **not** to use DI Frameworks.

Unit tests are about testing small parts, units, of our application. We can avoid the overhead of creating the DI Context. We'll be better off simply instantiating the subject under test manually.

On the other end, if we're writing integration, acceptance tests, or any different situation when we might need to test our application end-to-end, well, in that case, a suitable DI Framework could be our best friend.

Let's move on to unit tests **with** a DI Framework for demonstration purposes only.

```java
public final class MailCollectorAppTest extends AbstractModule {
  private MailService gmailServiceMock;
  private MailService microsoftServiceMock;
  private MailService thirdServiceMock;

  private MailCollectorApp sut;

  private Faker faker;

  @Override
  public void configure() {
    var listBinder = newSetBinder(binder(), MailService.class);
    listBinder.addBinding().toInstance(gmailServiceMock);
    listBinder.addBinding().toInstance(microsoftServiceMock);
    listBinder.addBinding().toInstance(thirdServiceMock);

    bind(MailEngine.class).to(RobustMailEngine.class).in(Scopes.SINGLETON);
  }

  @BeforeEach
  public void initialize() {
    faker = new Faker();

    gmailServiceMock = mock(MailService.class);
    microsoftServiceMock = mock(MailService.class);
    thirdServiceMock = mock(MailService.class);

    var injector = Guice.createInjector(this);

    sut = injector.getInstance(MailCollectorApp.class);
  }

  @Test
  @DisplayName(
      "make the services mocks return no mail and validate the return string as 'No mail found'")
  public void getMail_noMailExists_returnsNoMailFound() {
    willReturn(emptyList()).given(gmailServiceMock).getMail();
    willReturn(emptyList()).given(microsoftServiceMock).getMail();
    willReturn(emptyList()).given(thirdServiceMock).getMail();

    then(sut.getMail()).isEqualTo("No mail found.");
  }

  @Test
  @DisplayName(
      "make the services return legitimate mail and validate the return string as expected")
  public void getMail_foundMail_returnsExpectedString() {
    var mail1 =
        GmailImpl.builder()
            .from(faker.internet().emailAddress())
            .subject(faker.lorem().sentence())
            .build();
    var mail2 =
        MicrosoftImpl.builder()
            .from(faker.internet().emailAddress())
            .subject(faker.lorem().sentence())
            .build();
    var mail3 =
        MicrosoftImpl.builder()
            .from(faker.internet().emailAddress())
            .subject(faker.lorem().sentence())
            .build();

    willReturn(List.of(mail1)).given(gmailServiceMock).getMail();
    willReturn(List.of(mail2, mail3)).given(microsoftServiceMock).getMail();
    willReturn(emptyList()).given(thirdServiceMock).getMail();

    then(sut.getMail().split(System.lineSeparator()))
        .containsOnly(mail1.toString(), mail2.toString(), mail3.toString());
  }
}
```

We created the injector with a different module than the one we've used for the app (*DIModule*).

In this case, we extended the test class to be a module in itself. Injecting our mocks instead of the real *GmailService* and *MicrosoftService*. We also added a third mail service, demonstrating how easy it is. :grin:

The *RobustMailEngine* was not mocked because there was no real reason to do so, but it could have been easily replaced with a mock or a spy.

The test class behaved exactly like the main app, except for the services being mocks instead of real objects.

[0]: https://github.com/TomerFi/dependency-injection-java-part2-tutorial
[1]: https://dev.to/tomerfi/dependency-injection-in-java-is-easy-part-1-a-mear-design-pattern-2l8
[3]: https://dev.to/tomerfi/dependency-injection-in-java-is-easy-part-3-leveraging-with-spring-context-gcc