Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

More Guice Please: Re-Learning Google's DI Library (Part 1)

DZone's Guide to

More Guice Please: Re-Learning Google's DI Library (Part 1)

With the rise of Scala's popularity, it might be a good time to brush up (or learn about) Google Guice to see how it applies to both Java and Scala-based services.

· Java Zone
Free Resource

Just released, a free O’Reilly book on Reactive Microsystems: The Evolution of Microservices at Scale. Brought to you in partnership with Lightbend.

Google Guice is used as a lightweight dependency injection framework that further assists developers in modularizing their applications. Google shared this very useful library with the development community in 2010 in between the Java SE 6 and Java SE 7 releases. This library is used in some of Java’s (and now Scala’s) most prominent libraries and platforms, such as the Simian Army platform shared by Netflix.

We will begin our discussion of Google Guice with its Module interface. In the Guice developers’ own words, ‘A Guice-based application is ultimately composed of little more than a set of modules and some bootstrapping code.’ We will not be using this interface directly, but it gives us a very good context from which to start. Instead, we will be extending the abstract class that implements it — intuitively named AbstractModule.

If you ever get a chance to look at the Module interface Javadoc or source code, you’ll see a configure method taking a parameter of type Binder.

…

Interface Module{
    void configure(Binder binder);
}

Listing 1: Google Guice's module interface


We have plenty of time to talk about the Binder interface. For now, we’ll just take notice of the power and simplicity of the Google Guice library.

In the subtitle of this tutorial, we say we are “re-learning” Google Guice because, with the growing adoption of the Scala programming language, it is necessary to re-learn libraries like Guice so that we are able to use them to build not only Java-based services, but also Scala-based services. Continuing our discussion, one thing we should point out is that, when we extend the AbstractModule abstract class, we do not override the configure method of Listing 1, but a configure method without parameters. In fact, if we try to override the method from Listing 1, you’ll get a complaint from either your compiler or IDE. No, this is not magic. It may be worthwhile to take a look at the AbstractModule source to see why this is the case.

...

public abstract class AbstractModule implements Module {
    Binder binder;
    public final synchronized void configure(Binder builder) {
        ...
    }

    protected abstract void configure();

    protected Binder binder() {
        ...
    }

    ...

Listing 2: AbstractModule abstract class


As we see from Listing 2, the configure method from Listing 1 is final and so cannot be overridden. The way this class is structured, we will be “building” an instance of Binder within the body of our overriding configure method. This is typically done with the bind and install methods inherited from AbstractModule. The install method is fairly straightforward, since it can only accept a parameter of type Module. You’ll notice the bind method will take parameters of type Class, Key, or TypeLiteral. The Key and TypeLiteral types are part of the Guice library.

You can probably guess that using the bind method takes more thought than just using the install method with a neatly packaged module. To ease things, though, the bind method comes with a fairly intuitive Embedded Domain-Specific Language (EDSL). We will give some examples, which will be helpful since developers typically use bind more often than install. Both methods, as aforementioned, act on a Binder instance.

Before we get into some examples, let me just show you a simple design approach some developers have found useful. That is to extend Guice’s AbstractModule with an application-specific abstract class that overrides the configure method with an empty implementation. A demonstration of this is shown in Listing 3.

package com.uequations.demo.module

...

abstract class AppNameModule extends AbstractModule{
    override def configure():Unit = { 
    }
}

Listing 3: Abstract extension of AbstractModule (Scala)


This is just a way of making overriding the configure method optional. We’ll talk about these other options later. Also, down the road, you may decide to add methods in this class you may find helpful.

Let’s see if we can go through some simple examples starting with a typical XService/XServiceImpl example. In this case, after creating the appropriate XService trait and XServiceImpl extending it, you could extend AppNameModule in the following way:

package com.uequations.demo.module

import com.uequations.demo.service.{XService, XServiceImpl}

object XServiceModule extends AppNameModule {

    override def configure(): Unit = {
        bind(classOf[XService]).to(classOf[XServiceImpl])
    }
}

Listing 4: Module binding XService and XServiceImpl


Below demonstrates code using the XService/XServiceImpl binding from Listing 4:

package com.uequations.demo.app

import com.google.inject.Guice
import com.uequations.demo.module.XServiceModule
import com.uequations.demo.service.XService

object DemoApp {

    def main(args:Array[String]): Unit ={
        val injector = Guice.createInjector(XServiceModule)
        val instance = injector.getInstance(classOf[XService])
        instance.doSomething()
    }
}

Listing 5: How to make use of binding


Here, we use the static createInjector method, but there are other ways of making use of a binding.

We will discuss that next. See you then!

Strategies and techniques for building scalable and resilient microservices to refactor a monolithic application step-by-step, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
java ,google guice ,dependency injection ,scala ,tutorial

Published at DZone with permission of Mensah Alkebu-Lan. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}