hotmeatballsoup
hotmeatballsoup

Reputation: 625

Akka actor cannot send self a PoisonPill

Java/Akka here. I have the following actor:

public class MyActor extends AbstractActor {
    private Logger log = LoggerFactory.getLogger(this.getClass());

    public MyActor() {
        super();
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
            .match(Init.class, init -> {
                log.info("Sending myself a Poison Pill...");
                self().tell(PoisonPill.getInstance(), self());
            }).match(PoisonPill.class, poisonPill -> {
                log.info("Got the Poison Pill...");
                context().system().terminate();
            }).build();
    }
}

When it receives an Init message, I see the following log statement written:

Sending myself a Poison Pill...

But I never see:

Got the Poison Pill...

Furthermore the app just sits there and does not shut down as expected. Is there something in my use of self().tell(PoisonPill.getInstance(), self()) which prevents it from receiving the message and shutting down?

Upvotes: 3

Views: 416

Answers (1)

Jeffrey Chung
Jeffrey Chung

Reputation: 19527

The log message doesn't appear because PoisonPill is an AutoReceivedMessage. An AutoReceivedMessage is a special type of message that Akka handles internally and is not meant to be pattern-matched in user code.

One way to shut down the actor system once the actor is "poisoned"/stopped is to override the actor's postStop() method:

@Override
public Receive createReceive() {
  return receiveBuilder()
    .match(Init.class, init -> {
      log.info("Sending myself a Poison Pill...");
      self().tell(PoisonPill.getInstance(), ActorRef.noSender());
    })
    .build();
}

@Override
public void postStop() {
  getContext().getSystem().terminate();
}

Upvotes: 5

Related Questions