in  Java
play guice akka java

Play Framework Actor Pooling with Guice (Java)

Working with the Play! Framework means working with Akka, intentionally or not. But working with Akka Actors can be tricky, especially when it comes to dependency injection. Play! 2.4 uses Google’s Guice for DI and of course it has the ability to also bind Actors so an ActorRef can be injected anywhere.

Single Actor DI

Biding and injecting one single Actor is simple and well documented . Just bind it in a Module:

package modules;

import actors.MyExampleActor;
import com.google.inject.AbstractModule;
import play.libs.akka.AkkaGuiceSupport;

public class ActorModule extends AbstractModule implements AkkaGuiceSupport {

    public static final String EXAMPLE_ACTOR_DI_NAME = "my-example-actor";

    @Override
    protected void configure() {
        bindActor(MyExampleActor.class, EXAMPLE_ACTOR_DI_NAME);
    }
}

Enable the module in the app configuration:

play.modules.enabled = ${play.modules.enabled} [
  modules.ActorModule
]

Now you can inject the bound actor into every class using the @Inject and @Named annotation, e.g. in a Controller:

Keep in mind: Actors should always be injected as ActorRef and not as the concrete class which has been implemented.

package controllers;

import akka.actor.ActorRef;
import akka.util.Timeout;
import modules.ActorModule;
import play.mvc.Controller;
import play.mvc.Result;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;

import javax.inject.Inject;
import javax.inject.Named;
import java.util.concurrent.TimeUnit;

public class AssetController extends Controller {

    @Inject
    @Named(ActorModule.EXAMPLE_ACTOR_DI_NAME)
    ActorRef exampleActor;

    public Result publish(String assetType, String assetUuid) {
        FiniteDuration duration = Duration.create(5, TimeUnit.SECONDS);
        String response = Await.result(
                ask(exampleActor, "ask something", new Timeout(duration)).mapTo(classTag(Strijg.class)),
                duration
        );
        return ok(response);
    }
}

// disclaimer: Stuff like error handling and message protocols intentionally left out in favor of clarity

Actor Pools

As you maybe know, there is the possibility to create pools of Actors instead of only one single instance. A pool behaves like a single actor, using a router to distribute messages to different child actors. The configuration options are huge, but most of the time, I personally only need an option to bind an actor pool using round robin distribution. No problems to achive this using the Akka configuration, but I could not find any documentation how to combine it using Play / Guice DI (in Java).

It turned out, that it is simple once you know it. Just pass the props of a RoundRobinPool to the bindActor method as a third argument:

bindActor(MyExampleActor.class, EXAMPLE_ACTOR_DI_NAME, p -> new RoundRobinPool(5).props(p));

Now, instead of a single instance of MyExampleActor there is a pool of 5 of them waiting for messages.

The example works for Play! Framework 2.4 using Java 8 and will maybe break in future versions.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket