Typesafe Activator

Play with Guice

Play with Guice

typesafehub
Source
January 31, 2014
playframework guice dependency-injection

This is a Play example that uses Google Guice (https://code.google.com/p/google-guice/) for runtime dependency injection.

How to get "Play with Guice" on your computer

There are several ways to get this template.

Option 1: Choose play-guice in the Typesafe Activator UI.

Already have Typesafe Activator (get it here)? Launch the UI then search for play-guice in the list of templates.

Option 2: Download the play-guice project as a zip archive

If you haven't installed Activator, you can get the code by downloading the template bundle for play-guice.

  1. Download the Template Bundle for "Play with Guice"
  2. Extract the downloaded zip file to your system
  3. The bundle includes a small bootstrap script that can start Activator. To start Typesafe Activator's UI:

    In your File Explorer, navigate into the directory that the template was extracted to, right-click on the file named "activator.bat", then select "Open", and if prompted with a warning, click to continue:

    Or from a command line:

     C:\Users\typesafe\play-guice> activator ui 
    This will start Typesafe Activator and open this template in your browser.

Option 3: Create a play-guice project from the command line

If you have Typesafe Activator, use its command line mode to create a new project from this template. Type activator new PROJECTNAME play-guice on the command line.

Option 4: View the template source

The creator of this template maintains it at https://github.com/typesafehub/play-guice#master.

Option 5: Preview the tutorial below

We've included the text of this template's tutorial below, but it may work better if you view it inside Activator on your computer. Activator tutorials are often designed to be interactive.

Preview the tutorial

Play with Dependency Injection using Google Guice

Dependency injection is a design pattern that frees your code from creational concerns, making your code cleaner and easier to test.

This tutorial illustrates how easy it is to use a dependency injection framework with Play. Guice is used here, however other dependency injection frameworks such as Spring can be supported in a similar manner.

Although Scala is used here, Play and Java can also easily use dependency injection frameworks. Check out the Play Spring Data example for a Java example of using Spring with Play after this tutorial.

This tutorial will take about 10 minutes to complete and assumes that you are already familiar with the basics of a Play application.

The Mission

The mission is to use the familiar starting point of a Play application and enhance it with dependency injection. We will be taking the Application class and injecting a a TextGenerator instance into it. TextGenerator is an abstract class and we have a concrete implementation of it in the form of WelcomeTextGenerator.

TextGenerator is a rudimentary service that simply generates text. You'll have more useful services in your code e.g. a repository service that is backed by a concrete class to communicate with a database. By using dependency injection we can configure the type of service required outside of the class that needs to call on it.

@Inject and @Singleton

@Inject is the JSR-330 standard for declaring that an object is required to be injected into another object. @Singleton is also part of JSR-330 and declares that a single instance is to be shared across multiple injections.

Our shared Application instance declares that it requires an instance of the TextGenerator type. We are using what is known as "constructor injection" here, the alternate being what is known as "setter injection". We prefer constructor injection as once that property is assigned it cannot be changed i.e. the value is immutable and inherently thread safe.

TextGenerator does not require anything special in order to be "injectable" i.e. something that can be injected into something else. We have declared TextGenerator as an abstract class here but it can be any type i.e. a concrete class or a trait (we have used an abstract class in recognition of the "is-a" relation between vs "has-a").

WelcomeTextGenerator is a concrete implementation of the TextGenerator. Having the implementation separated from the injectable type frees you to provide alternate implementations of it. For this project the application will share a single instance of WelcomeTextGenerator; hence the @Singleton annotation. Our tests will use a mocked version of WelcomeTextGenerator so that the classes that are injected with a TextGenerator can be easily tested.

Note that although we use @Singleton on the Application and WelcomeTextGenerator, these "scopes" can be overridden when it comes to binding. Binding is discussed next.

Binding

Global brings the dependency injection system to life by establishing a dependency graph and then providing Play a means of resolving object instances under its management.

First of all an Injector is created. An Injector is responsible building the dependency graph. Our injector states that whenever a type of TextGenerator is required then use an instance of WelcomeTextGenerator.

The next thing is that getControllerInstance will return object instances from the dependency injection system.

An interesting point to note is that the Global object is the only place in our application where there is Guice specific code. This is because JSR-330's @Inject and @Singleton annotations are being used. You should therefore be able to use this project's main files and other dependency injection frameworks with very little modification.

Routing Concerns

By convention Play looks for an object instance when resolving routes. However routes can be configured so that locating the route instance will call upon the Global object's getControllerInstance method. A simple "@" symbol in front of the controller method path in the routes is all that is required i.e. @controllers.Application.index.

Testing

ApplicationTest illustrates a benefit of dependency injection where a mock of the TextGenerator is used for unit testing purposes. Using a mock makes testing easier as we are not interested in testing the actual type implemented by the mock - just the calls that we make upon it.

The ApplicationIT is an integration test that brings our dependency injection system into life and sets expectations on what should be seen upon invoking the controller.

ApplicationFT is a functional test. Note that the entire application is run and the test is around sending HTTP requests and verifying their responses. Just as with the integration test, the dependency injection system is tested thoroughly.

Conclusion

This tutorial has introduced how Google Guice can be used for developing Play applications. Other dependency injection systems such as Spring can be similarly incorporated. The Global object establishes the dependency injection system and the routes file requires classes to be referenced via the '@' symbol.

By separating the creational concerns from a class, classes can remain focused on the job they are intended to do and have their code remain clean and devoted to that purpose. In addition your classes will become more testable, particularly from a unit test perspective, given that injectable types can easily be mocked.

comments powered by Disqus