Java 8, Guice 4.0 and Akka 2.3.9 here. I am trying to figure out how to annotate my actor classes with JSR330-style @Inject
annotations, and then wire them all up via Guice.
But literally every single article I have read (some examples below) either uses Scala code examples, a criminally-old version of Guice, or a criminally-old version of Akka:
So, given the following Guice module:
public interface MyService {
void doSomething();
}
public class MyServiceImpl implements MyService {
@Override
public void doSomething() {
System.out.println("Something has been done!");
}
}
public class MyActorSystemModule extends AbstractModule {
@Override
public void configure() {
bind(MyService.class).to(MyServiceImpl.class);
}
}
And given the FizzActor
that gets injected with a MyService
:
public class FizzActor extends UntypedActor {
private final MyService myService;
@Inject
public FizzActor(MyService myService) {
super();
this.myService = myService;
}
@Override
public void onReceive(Object message) {
// .. Do fizz stuff inside here.
}
}
Then I ask: How do I rig up MyActorSystemModule
to create instances of FizzActor
and properly inject them with Java (not Scala!)?
Please note: FizzActor
is not the only actor in my actor system!
So I have been playing around with Akka and Guice recently alot and I feel that those two don't play too well together.
What I suggest is you take a similar approach what Play is doing.
Kutschkem's answer comes closest to that.
Creator
. Don't try to do@AssisstedInject
in yourCreator
as this will imply that you will need a new creator for every Actor that you want to create. Personally I believe that initializing this in the actor is better done through messaging.Here is a code example using current Akka 2.5. This is the preferred setup we chose for our Akka 2.5 deployment. For brevity I did not provide the Module, but it should be clear from the way the Members are injected, what you want to provide.
Code:
Generic Akka Guice integration without dependency on Play, keeping in mind, not the only actor should be created in the actor system.
Generic ActorRefProvider to create ActorRef for each Actor
Usage example
Unless you are trying to bind
UntypedActor
toFizzActor
, then you can just inject it into other classes as is:If you're trying to bind it to the interface, you'll need to specifically do that in the module:
Edit:
What about using
@Named
to distinguish theUntypedActor
, e.g.:Then in your module you could do the akka lookups:
Use Creator to create
ActorRef
s in provider methods of your guice module. To distinguish between the differentActorRef
s, which are untyped, use annotations on your provider methods and injection points as you would any guice system. For example,In your guice module:
Then to use the actor service, inject a specific
ActorRef
:It looks cleaner if the
Props.create(..)
clause is a static factory method in your actor class.In case anyone found this question, you need to use IndirectActorProducer, I referred to the Spring example and changed it to use Guice instead.
In the module
Use an akka Creator:
Then use Props.create with your shiny new guice-based creator.
Disclaimer: I don't actually know Akka, the mentioned information comes from browsing the documentation and JavaDoc.