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

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s