modified hello world in Akka - why so many lost messages and dead letters?

akka, java

Solution

As @Noah astutely pointed out, when the `App` actor receives a `DONE` response, it is stopping itself. Now, stop just stops any more messages from being recevied by the actor but it will still process what was in its mailbox prior to being stopped, so more than 1 message will likely be processed. Once this actor is stopped, the `ActorRef` that was passed along to the other actor via `getSelf` is now pointing to `DeadLetter` and that's why you start to see messages being routed to deadletter. If you really want to test this fully, decrement a counter (that starts out at 1000) each time you receive a response in the `App` actor. When it reaches 0, you can safely stop it:

public class App extends UntypedActor {
  private int counter = 1000;

  @Override
  public void preStart() {
    // create the greeter actors
    List<ActorRef> actorRefs = new ArrayList();
    for (int i = 0; i < counter; i++) {
        final ActorRef greeter = getContext().actorOf(Props.create(Greeter.class, i));
        this.getContext().watch(greeter);
        actorRefs.add(greeter);
    }
    // tell it to perform the greeting
    for (ActorRef actorRef : actorRefs) {
        actorRef.tell(Greeter.Msg.GREET, getSelf());
    }
  }

  @Override
  public void onReceive(Object msg) {

    if (msg instanceof DeadLetter) {
        System.out.println(msg);
    } else if (msg == Greeter.Msg.DONE) {
        if (--counter <= 0){
          getContext().stop(getSelf());
        }

    } else {
        unhandled(msg);
    }
  }

}

Problem

Complete beginner here in Akka 2.2, trying a modified version of the Hello World. The modification is that I create 1000 actors instead of one. Running it, I don't get all 1000 hello worlds returned, with this error trace, repeated for several messages: [07/23/2013 22:22:45.924] [Main-akka.actor.default-dispatcher-2] [akka://Main/user/app/$Si] Message [net.clementlevallois.akkatest.Greeter$Msg] from Actor[akka://Main/user/app#1478796310] to Actor[akka://Main/user/app/$Si#-1309206213] was not delivered. 1 dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'. The two classes: ``` public class App extends UntypedActor { @Override public void preStart() { // create the greeter actors List<ActorRef> actorRefs = new ArrayList(); for (int i = 0; i < 1000; i++) { final ActorRef greeter = getContext().actorOf(Props.create(Greeter.class, i)); this.getContext().watch(greeter); actorRefs.add(greeter); } // tell it to perform the greeting for (ActorRef actorRef : actorRefs) { actorRef.tell(Greeter.Msg.GREET, getSelf()); } } @Override public void onReceive(Object msg) { if (msg instanceof DeadLetter) { System.out.println(msg); } else if (msg == Greeter.Msg.DONE) { // when the greeter is done, stop this actor and with it the application getContext().stop(getSelf()); } else { unhandled(msg); } } } public class Greeter extends UntypedActor { String input; public static enum Msg { GREET, DONE; } public Greeter(int i) { input = String.valueOf(i); } @Override public void onReceive(Object msg) { if (msg == Msg.GREET) { System.out.println("Hello World! " + input); getSender().tell(Msg.DONE, getSelf()); } else { unhandled(msg); } } } ``` I would appreciate any help on debugging, and advice on whether creating lists of actors as done here is alright or not.

Original source