Typesafe Activator

Akka Java Spring

Akka Java Spring

typesafehub
Source
October 7, 2014
basics akka java spring starter

Illustrates how to Inject dependencies into Akka actors using Spring in Java

How to get "Akka Java Spring" on your computer

There are several ways to get this template.

Option 1: Choose akka-java-spring in the Typesafe Activator UI.

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

Option 2: Download the akka-java-spring project as a zip archive

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

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

Option 3: Create a akka-java-spring 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 akka-java-spring on the command line.

Option 4: View the template source

The creator of this template maintains it at https://github.com/typesafehub/activator-akka-java-spring#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 Spring. You will be guided through the different parts used to integrate Akka with Spring 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 basically consist of a single actor defined in the CountingActor.java file. This actor uses a service defined in the CountingService.java file to increment a value. The CountingService is wired into the Actor via Spring.

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

  • Initializes Spring
  • Creates an actor system
  • Creates a CountingActor
  • Sends a couple of messages to the actor 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.java application.

Running the Test

There is also a Junit test for the CountingActor located in the SpringTest.java file. It is structured in the same way as the Main application.

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

Exploring the Code: The Akka Extension

To be able to use the Spring application context to let Spring 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 SpringExtension.java file.

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

On this extension, the SpringExt class, there are only two methods, initialize(ApplicationContext applicationContext) that is used during startup to initialize the extension with the right Spring application context, and props(String actorBeanName) that constructs a Props from an actor bean name, that is used to create an actor.

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

Exploring the Code: The Spring Actor Producer

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

The SpringActorProducer 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 Spring Application Configuration

To tie everything together and let the Akka actor system know about the Spring application context, we have a Spring configuration defined in the AppConfiguration.java file.

The AppConfiguration has a single method actorSystem that is responsible for creating the ActorSystem singleton in this Spring application. The code creates the actor system and then initializes the SpringExtension with the Spring application context needed by the SpringActorProducer to create actor instances from bean names.

Creating a Test Counting Service

Since we want to be able to test our actor thoroughly, let's create 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.

Open the empty TestCountingService.java file, and add the code below. Remember to save the file afterwards.

package sample;

import javax.inject.Named;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * A test counting service that wraps the normal counting service
 * and keeps track of the number of times that it has been called.
 */
@Named("TestCountingService")
public class TestCountingService extends CountingService {

  private AtomicInteger called = new AtomicInteger(0);

  @Override
  public int increment(int count) {
    called.incrementAndGet();
    return super.increment(count);
  }

  /**
   * How many times we have called this service.
   */
  public int getNumberOfCalls() {
      return called.get();
  }
}

A Closer Look at the Test Counting Service

Lets take a closer look at the newly created test counting service in the file TestCountingService.java

The class TestCountingService inherits from CountingService and overrides the method increment on line 16. 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 24 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.

One important thing to note is the annotation on line 10 @Named("TestCountingService"). This will allow us to wire together the TestCountingService with the CountingActor in the test during the next step.

Wire up the Test Counting Service

Now that you have created a test counting service it is time to start using it in the test.

Open the SpringTest.java file. And between line 24 and 25, right after ctx.scan("sample");, add the two lines below. Remember to save the file afterwards.

// wire up the test service instead of the normal service
ctx.registerAlias("TestCountingService", "CountingService");

This alias will make sure that when we look for a bean named CountingService we will instead get the one named TestCountingService. Check that the tests are still green on the Test tab.

We would also like to check that the actor actually called the service the right number of times by using the getNumberOfCalls method. Add the code below to the SpringTest.java file. on line 46, just above the comment // shut down the actor system. Remember to save the file afterwards.

// check that it called the TestCountingService the right number of times
TestCountingService testService = ctx.getBean(TestCountingService.class);
assertEquals(3, testService.getNumberOfCalls());

Check that the tests are still green on the Test tab.

Conclusions

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

The Akka extension SpringExtension.java, the actor producer SpringActorProducer.java and the application configuration AppConfiguration.java can be reused as the basis for your own Spring application.

comments powered by Disqus