Modern Akka DI with Guice

Use an akka Creator:

public class GuiceCreator<T> implements Creator<T> {
 Class<T> clz;
 Module module;
 /*Constructor*/

 public T create() {
    Injector injector = Guice.createInjector(this.module);
    return injector.getInstance(this.clz);
  }
}

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.


Unless you are trying to bind UntypedActor to FizzActor, then you can just inject it into other classes as is:

class SomeOtherClass {

    @Inject 
    public SomeOtherClass(FizzActor fizzActor) {
        //do stuff
    }
}

If you're trying to bind it to the interface, you'll need to specifically do that in the module:

public class MyActorSystemModule extends AbstractModule {
    @Override
    public void configure() {
        bind(MyService.class).to(MyServiceImpl.class);
        bind(UntypedActor.class).to(FizzActor.class);
    }
}

Edit:

What about using @Named to distinguish the UntypedActor, e.g.:

class SomeOtherClass {

    @Inject 
    public SomeOtherClass(@Named("fizzActor")UntypedActor fizzActor, @Named("fooActor") UntypedActor fooActor) {
        //do stuff
    }
}

Then in your module you could do the akka lookups:

public class MyActorSystemModule extends AbstractModule {

    ActorSystem system = ActorSystem.create("MySystem");

    @Override
    public void configure() {
        bind(MyService.class).to(MyServiceImpl.class);
    }

    @Provides
    @Named("fizzActor")
    public UntypedActor getFizzActor() {
        return system.actorOf(Props.create(FizzActor.class), "fizzActor");
    }

    @Provides
    @Named("fooActor")
    public UntypedActor getFooActor() {
        return system.actorOf(Props.create(FooActor.class), "fooActor");
    }
}

Use Creator to create ActorRefs in provider methods of your guice module. To distinguish between the different ActorRefs, which are untyped, use annotations on your provider methods and injection points as you would any guice system. For example,

In your guice module:

@Override
protected void configure() {
    bind(ActorSystem.class).toInstance(ActorSystem.apply());
    bind(FizzService.class).toInstance(new FizzServiceImpl());
}

@Provides @Singleton @Named("fizzActor")
ActorRef serviceActorRef(final ActorSystem system, final FizzService fizzService) {
    return system.actorOf(Props.create(new Creator<Actor>() {
        @Override
        public Actor create() throws Exception {
            return new FizzActor(fizzService);
        }
    }));
}

Then to use the actor service, inject a specific ActorRef:

class ClientOfFizzActor {
    @Inject
    ClientOfFizzActor(@Named("fizzActor") ActorRef fizzActorRef) {..}
}

It looks cleaner if the Props.create(..) clause is a static factory method in your actor class.

Tags:

Java

Guice

Akka