Add the following to your build.sbt:
resolvers += "release repository" at "http://chanan.github.io/maven-repo/releases/"
resolvers += "snapshot repository" at "http://chanan.github.io/maven-repo/snapshots/"
Add to your libraryDependencies:
"akkaguice" %% "akkaguice" % "0.8.3"
First, create or edit conf/play.plugins. Add the line (The number in front of the plugin is the load order inside your play app):
10000:akkaGuice.AkkaGuicePlugin
In Global.java create an Injector using AkkaGuiceModule. You may also pass in your own GuiceModules, as in the example below. Next, in the onStart callback method pass the injector to AkkaGuice.InitializeInjector():
public class Global extends GlobalSettings {
private Injector injector;
public <A> A getControllerInstance(Class<A> clazz) throws Exception {
return injector.getInstance(clazz);
}
@Override
public void onStart(Application arg0) {
injector = Guice.createInjector(new AkkaGuiceModule(), new GuiceModule());
AkkaGuice.InitializeInjector(injector);
}
}
AkkaGuice will scan your application code. This will make Actors available in Guice to be injected into your controllers or services.
AkkaGuice will be default register your actors by the class name. If a collision occurs, it will use the fully qualified class name of the actor. An example of this is the HelloActor in the sample project. There is one registered as services.HelloActor and one as services.schedule.HelloActor. You may also name your actor using @Named annotation (java.inject.Named).
For example:
@Named("AnnotatedActor") @Singleton
public class AnnotatedWithNameActor extends UntypedActor {
@Override
public void onReceive(Object arg0) throws Exception {
Logger.info("Hello from actor using named annotation");
}
}
An actor marked with the @Singleton annotation will return the same ActorRef from Guice. If the Actor is not annotated as a @Singleton, a new ActorRef will be returned each time. Also, a non-singleton actor will be registered in AkkaGuice's PropsContext (See below: "On Demand Creation of Actors").
You may have seen the warning in the akka documentation in the Dependancy Injection section regarding using Singleton attribute. The warning applies to returning the same actor class. In the case of AkkaGuice we are returning the same ActorRef. This still allows Akka to restart the actor if needed.
As mention above, when the annotation does not have a name, Actors are bound to ActorRefs with a name of the class if there are no collision. Otherwise they are bound to a name of the fully qualified class name. For example, in the sample app in the Application controller the HelloActor is injected with the fully qualified name as two HelloActors exist in the project:
private final ActorRef service;
@Inject
public Application(@Named("services.HelloActor") ActorRef service) {
this.service = service;
}
Any services injected into actors will be resolved as well:
public class HelloActor extends UntypedActor {
private final SayHello hello;
@Inject
public HelloActor(SayHello hello) {
this.hello = hello;
}
...
}
Per Request ActorRefs can also be requested from Guice on demand. All injections will still be resolved. This example is from services.HelloActor:
final ActorRef perRequestActor = Akka.system().actorOf(PropsContext.get(PerRequestActor.class));
Or:
final ActorRef perRequestActorByName = getContext().actorOf(PropsContext.get("PerRequest"));
AkkaGuice also provides for automatic scheduling of Actors. A String "tick" will be sent to the Actor on the schedule set by the annotation.
As seen in the services.schedule.HelloActor class, use the schedule annotation to periodically ping your actor:
@Schedule(initialDelay = 1, timeUnit = TimeUnit.SECONDS, interval = 2)
To ping your actor one time use the ScheduleOnce annotation. This example is located in services.schedule.HelloOnceActor:
@ScheduleOnce()
In this case, the defaults of the annotation were used:
If values are entered in the conf file they override the values of the annotation.
The following entries can be entered in the conf file:
services.schedule.HelloRepeatConfigActor.initialDelay = 4 seconds
services.schedule.HelloRepeatConfigActor.interval = 2 seconds
The following can be entered via config:
services.schedule.HelloOnceConfigActor.initialDelay = 5 seconds
You can disable both types of scheduled actors via config:
services.schedule.NotEnabledActor.enabled = false