I have an Actor System that I want to start and have live until a particular actor, the Destructor
, receives a ShutdownNow
message. When it receives such a message, it basically executes the equivalent of a shutdown hook, shuts the entire actor system down, and then the parent JVM process/main thread shuts down: Something like this:
class MyApp {
static void main(String[] args) {
// Do some stuff before starting the actor system.
ActorSystem actorSystem = ActorSystem.create(“myapp-actorsys”)
ActorRef initializer = actorSystem.actorOf(Props.create(Initializer) “initializer”)
Inbox inbox = Inbox.create(actorSystem)
inbox.send(initializer, new Initialize())
// Now the actor system is initialized and is running
// Maybe its processing data off a message broker, etc.
// Here I’d like to wait until the actor system shuts down (see Destructor below)
while(actorSystem.isRunning()) { }
// Now do some final tasks.
} // <- end of main thread/parent JVM process
}
class Destructor extends UntypedActor {
@Override
void onReceive(Object msg) {
if(msg instanceof ShutdownNow) {
// Shut down the actor system such that actorSystem.isRunning()
// will return true.
}
}
}
The idea here is that the parent JVM process stays alive unless interrupted by the underlying OS (sigkill, etc.) or something inside the actor system signals a ShutdownNow
message to the appropriate actor.
How do I implement this?
Without knowing what the exact setup is you are using:
The Java process won't stop until your actor system stops. So you need to do nothing, but send the shutdown command from your Destructor Actor.
The following code works for me (both with stopping the process from within the process with the actor and from outside with kill):
import java.util.concurrent.TimeUnit;
import scala.concurrent.duration.Duration;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.actor.UntypedActor;
public class MyApp {
public static void main(String[] args) {
// Do some stuff before starting the actor system.
System.out.println("Start Actor System");
ActorSystem actorSystem = ActorSystem.create("myapp-actorsys");
ActorRef destructor = actorSystem.actorOf(Props.create(Destructor.class));
//Java process won't shut down before actor system stops
//Send message after timeout to stop system
actorSystem.scheduler().scheduleOnce(Duration.create(10, TimeUnit.SECONDS),
destructor, new ShutdownNow(), actorSystem.dispatcher(), null);
}
public static class Destructor extends UntypedActor {
public Destructor() {
}
@Override
public void onReceive(Object msg) {
if(msg instanceof ShutdownNow) {
//Shutdown system to stop java process
System.out.println("Stop Actor System");
getContext().system().shutdown();
}
}
}
public static class ShutdownNow {
}
}