Category Archives: Akka

Akka: Spring Integration

PROBLEM

To create Spring-managed prototype-scoped actors.

SOLUTION

The key to this solution is to create a custom implementation of IndirectActorProducer. From the documentation:-

“…This interface defines a class of actor creation strategies deviating from the usual default of just reflectively instantiating the Actor subclass. It can be used to allow a dependency injection framework to determine the actual actor class and how it shall be instantiated…”

First, create an implementation of IndirectActorProducer that creates the actor using Spring’s ApplicationContext.

public final class SpringActorProducer implements IndirectActorProducer {
    private final ApplicationContext applicationContext;
    private final Class<? extends Actor> actorClass;

    public SpringActorProducer(final ApplicationContext applicationContext, 
                               final Class<? extends Actor> actorClass) {
        this.applicationContext = applicationContext;
        this.actorClass = actorClass;
    }

    @Override
    public Actor produce() {
        return applicationContext.getBean(actorClass);
    }

    @Override
    public Class<? extends Actor> actorClass() {
        return actorClass;
    }
}

To prevent tedious auto-wiring ApplicationContext in every actor class to be passed to SpringActorProducer above, create a Spring-managed service that will do just that.

@Component
public final class SpringProps {
    private final ApplicationContext applicationContext;

    @Autowired
    public SpringProps(final ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public Props create(final Class<? extends Actor> actorClass) {
        return Props.create(SpringActorProducer.class, 
                            applicationContext, 
                            actorClass);
    }
}

Now, instead of creating the actors like this….

ActorRef master = actorSystem.actorOf(
                      Props.create(Master.class), "master");

ActorRef workerRouter = getContext().actorOf(
                            Props.create(Worker.class)
                                 .withRouter(new RoundRobinPool(5)),
                            "workerRouter");

… we will use the auto-wired SpringProps to create the actors…

@Autowire
private SpringProps springProps;

...

ActorRef master = actorSystem.actorOf(
                      springProps.create(Master.class), "master");
												 
ActorRef workerRouter = getContext().actorOf(
                            springProps.create(Worker.class)
                                       .withRouter(new RoundRobinPool(5)),
                            "workerRouter");

Make sure all actor classes are Spring-managed with prototype-scoped by annotating them with @Component and @Scope("prototype").

To see the full example, visit https://github.com/choonchernlim/test-akka-spring