Typesafe Activator

Akka Scala Guice

Akka Scala Guice

rocketraman
Source
March 9, 2015
akka guice dependency-injection scala starter

Demonstrates Akka DI with Guice and Scala

How to get "Akka Scala Guice" on your computer

There are several ways to get this template.

Option 1: Choose activator-akka-scala-guice in the Typesafe Activator UI.

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

Option 2: Download the activator-akka-scala-guice project as a zip archive

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

  1. Download the Template Bundle for "Akka Scala 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\activator-akka-scala-guice> activator ui 
    This will start Typesafe Activator and open this template in your browser.

Option 3: Create a activator-akka-scala-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 activator-akka-scala-guice on the command line.

Option 4: View the template source

The creator of this template maintains it at https://github.com/rocketraman/activator-akka-scala-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

Introduction

This tutorial aims to show you how to inject resources into Akka actors using Guice. You will be guided through the different parts used to integrate Akka with Guice and also create a test wrapper for a service and rewire the service used during testing without any code changes needed to the actor or the application classes.

Application Overview

The application consist of an actor defined in the CountingActor.scala file. This actor uses a service defined in the CountingService.scala file to increment a value. CountingService also uses AuditCompanion actor which in turn uses AuditBus actor. Audit actors are defined in the Audit.scala file. Service and actor dependencies are wired via Guice.

Note that ActorRefs are injected using top-level actors. This should be used sparingly to wire-up only top level components.

To drive the actor, there is a application defined in the Main.scala file that does the following:

  • Initializes Guice
  • Obtains the actor system from Guice
  • Creates two CountingActor instances via the Guice extension to demonstrate ActorRef injection scopes
  • Sends a couple of messages to the actors so that it uses the CountingService

Running the Application

The result of running the Main application is shown in the Run tab. On the left-hand side we can see the console output, which is "Got back 3" for the Main.scala application. You can also see output of the AuditBus actor, which demonstrates that AuditBus actor is created in Singleton scope and AuditCompanion is created every time new CountingActor is instantiated.

Running the Test

There is also a ScalaTest test for the CountingActor located in the CountingActorSpec.scala file. It is structured in the same way as the Main application.

The result of running the CountingActorSpec test is shown in the Test tab. On the left-hand side we can see the console output, which is "passed CountingActorSpec".

Exploring the Code: The Akka Extension

To be able to use the Guice application context to let Guice create and wire up our actors, we need to store it away in a place that is easily accessible from within the actor system. This is an ideal use case for what is called an Akka Extension. An extension can be thought of as a per actor system singleton and the one in this tutorial is defined in the GuiceAkkaExtension.scala file.

The extension consist of two parts. The GuiceAkkaExtension class that defines the methods used by Akka to create the extension for an actor system, and the GuiceAkkaExtensionImpl class that defines the methods and fields available on the extension.

On this extension, the GuiceAkkaExtensionImpl class, there are only two methods, initialize(injector: Injector) that is used during startup to initialize the extension with the right Guice injector, and props(actorName: String) that constructs a Props from an actor name, that is used to create an actor.

The Props creation uses the GuiceActorProducer that we will talk about next.

Exploring the Code: The Guice Actor Producer

To let Guice create the actor from a bean name we need a way to allow the Akka Props to delegate actor creation to Guice. This is done in the GuiceActorProducer.scala file.

The GuiceActorProducer implements the IndirectActorProducer interface which is a way to let the actor be created via a factory method. This interface has two methods that need to be implemented, actorClass that will return the type of the actor that will be created, and produce, that needs to create a new actor instance every time that it is called.

Exploring the Code: The Guice Application Configuration

To tie everything together, we have a Guice injector defined in the Main.scala file. The injector references the various pieces of the application:

  1. a ConfigModule.scala to inject a Typesafe Config object where necessary,
  2. an AkkaModule.scala to create an ActorSystem and initialize the Guice extension,
  3. a SampleModule.scala to bind the sample counting actor and service.
  4. and a AuditModule.scala to bind the ActorRef of Audit actors.

The AkkaModule has a ActorSystemProvider that is responsible for creating the ActorSystem in this Guice application, and the module binds the system as an eager singleton, which is useful to detect errors early in the application startup. The code creates the actor system and then initializes the GuiceAkkaExtension with the injector needed by the GuiceActorProducer to create actor instances from actor names. Note that the injector is itself injected by Guice into the ActorSystemProvider.

Testing the Counting Service

Since we want to be able to test our actor thoroughly, let's use a test counting service. In our tutorial it will just wrap the real counting service and do some extra book keeping, but it could just as easily be a complete mock of the service.

Lets take a closer look at the test counting service in the file TestCountingService.scala

The class TestCountingService inherits from CountingService and overrides the method increment on line 9. In that method it keeps track of how many times it has been called, by using an internal counter named called and then it delegates to the real counting service by calling super.increment(count)

It also has a method named getNumberOfCalls on line 14 that returns the value of the internal counter called that can be used during testing to verify how the service is being used by the actor.

Open the CountingActorSpec.scala file. At line 55, a test module that binds the TestCountingService to CountingService is added to our Guice configuration. The TestCountingService is defined in Singleton scope so that we can retrieve the same instance in the test as was used by the actor. The injector is created by the test with the basic required modules. Each test can also initialize the injector with the additional modules that may be required for testing.

The test verifies the right number of calls are made to the test service at line 74. It also verifies the audit companion is receiving audit messages at line 89 by mocking out the AuditCompanion actor using a Guice module that injects the TestProbe actor in its place.

Conclusions

You now have a working sample that uses Guice to inject a service or a test service into an actor. Feel free to experiment and change the actor CountingActor.scala, service CountingService.scala, test service TestCountingService.scala and test CountingActorSpec.scala.

The Akka extension GuiceAkkaExtension.scala, the actor producer GuiceActorProducer.scala and the application modules can be reused as the basis for your own Guice Akka application.

comments powered by Disqus