We are planning to use Akka and Akka Streams in a Jira server plugin, using the latest Plugin Framework (4) and Spring Scanner (2.x) versions.
Is there a recommended way of using Scala and Akka in a server plugin?
We need to make sure the actor system is properly terminated if the add-on is disabled.
Can we rely on OSGI BundleActivator as used and mentioned in Akka OSGI? In that case the code will look like
import akka.actor.{ Props, ActorSystem }
import org.osgi.framework.BundleContext
import akka.osgi.ActorSystemActivator
object Activator extends ActorSystemActivator {
def configure(context: BundleContext, system: ActorSystem) {
registerService(context, system)
val someActor = system.actorOf(Props[SomeActor], name = "someName")
someActor ! SomeMessage
}
}
Is there a more high-level way of achieving this without directly using BundleActivator
and BundleContext
? e.g. just using Spring annotations?
It was a while ago, so don’t sue me if the latest-and-greatest Spring usage pattern is different from now, but here’s how I did it:
public class DefaultActorSystemManager implements ActorSystemManager, ApplicationListener {
...
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent) {
// shut down any actor system created by an earlier instance of the plugin
actorSystemOption.foreach(shutdownActorSystem);
// create a new actor system
actorSystemOption = actorSystemFactory.create();
// Spawn actors, which are supervised by the system guardian.
accountantOption = actorSystemOption.map(spawnAccountant);
notifierOption = actorSystemOption.map(spawnNotifier);
primerOption = actorSystemOption.map(spawnPrimer);
...
} else if (event instanceof ContextClosedEvent) {
actorSystemOption.foreach(shutdownActorSystem);
actorSystemOption = Option.none();
}
}
private final Effect<ActorSystem> shutdownActorSystem = new Effect<ActorSystem>() {
@Override
public void apply(ActorSystem actorSystem) {
log.info("Shutting down actor system");
actorSystem.shutdown();
actorSystem.awaitTermination();
}
};
...
}
Worked just fine.
1 Like
Thanks a lot David. May I ask how did you pass (inject) specific actors (Accountant, Notifier, …) as dependencies to other components?
In this case I didn’t need to pass the actor references around, but it would be easy enough to add getter methods to the ActorSystemManager
interface, and inject that into other components.
1 Like