Jonathan Oheix
Jonathan Oheix

Reputation: 13

Akka Java : dead letters encountered

I'm creating actors in java with akka library to implement the Chord system. My goal here is to make two actors send messages to each other. But when I do so, I get the following error message :

[INFO] [12/24/2015 15:27:33.521] [globalSystem-akka.actor.default-dispatcher-5] [akka://globalSystem/user/ChordActor3] Message [messages.SuccessorFoundMessage] from Actor[akka://globalSystem/user/ChordActor0#1781934127] to Actor[akka://globalSystem/user/ChordActor3#-2019697728] 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'.

Here is the code of my Main class :

package classes;

import messages.JoinMessage;
import messages.PrintFingerTableMessage;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;

public class Main {

public static void main(String[] args) {

    final ActorSystem system = ActorSystem.create("globalSystem");


    ChordNode cn0 = new ChordNode(0);
    ChordNode cn3 = new ChordNode(3);


    final ActorRef actor0 = system.actorOf(Props.create(ChordActor.class),"ChordActor0");
    final ActorRef actor3 = system.actorOf(Props.create(ChordActor.class),"ChordActor3");


    PrintFingerTableMessage printFingerTableMessage = new PrintFingerTableMessage();
    JoinMessage joinMessage0 = new JoinMessage(cn0);
    JoinMessage joinMessage3 = new JoinMessage(cn3);


    actor0.tell(joinMessage0,null);
    actor0.tell(printFingerTableMessage,null);  

    actor3.tell(joinMessage3, actor0);
    actor3.tell(printFingerTableMessage,null);  


    system.shutdown();
}

}

And here is my class ChordActor :

package classes;

import java.util.ArrayList;

import messages.FindSuccessorMessage;
import messages.JoinMessage;
import messages.PrintFingerTableMessage;
import messages.SuccessorFoundMessage;
import akka.actor.ActorRef;
import akka.actor.UntypedActor;

public class ChordActor extends UntypedActor{
    private ChordNode chordNode;
    private FingerTable fingerTable;
    private ArrayList<Key> key = new ArrayList<Key>();
    private ActorRef predecessor;
    private ActorRef successor;

@Override
public void onReceive(Object message) throws Exception {


    if(message instanceof JoinMessage){
        this.chordNode=((JoinMessage) message).getChordNode();

        // if sender is null :
        if(getSender().toString().equals("Actor[akka://globalSystem/deadLetters]")){
            this.fingerTable= new FingerTable(this.chordNode,getSelf());
            this.predecessor=getSelf();
            this.successor=getSelf();
        }


        else{

            this.fingerTable= new FingerTable(this.chordNode);
            for(int i=0;i<this.fingerTable.getTable().size();i++){
                FindSuccessorMessage findSuccessorMessage = new FindSuccessorMessage(this.fingerTable.getTable().get(i).getLowBound(),i);
                getSender().tell(findSuccessorMessage, getSelf());
            }
        }
    }


    else if(message instanceof FindSuccessorMessage){
        ActorRef actorRef = this.fingerTable.findSuccessor(((FindSuccessorMessage) message).getId());
        int ligne = ((FindSuccessorMessage) message).getLigne();

        SuccessorFoundMessage successorFoundMessage = new SuccessorFoundMessage(actorRef,ligne);
        getSender().tell(successorFoundMessage,getSelf());
    }


    else if(message instanceof SuccessorFoundMessage){
        this.fingerTable.getTable().get(((SuccessorFoundMessage) message).getligne()).setSuccessor(((SuccessorFoundMessage) message).getActorRef());
    }

    else if(message instanceof PrintFingerTableMessage){
        System.out.println(this.fingerTable);       
    }
}
}

I searched on internet for solutions, but I didn't really understand how to solve my problem.

Thank you for your help.

Have a nice day !

Jonathan

Upvotes: 0

Views: 10417

Answers (1)

johanandren
johanandren

Reputation: 11479

When you system.shutdown() your actor system this will lead to that the actors are stopped. As you do not in any way wait for the "work" of your actors to complete, they may have processed all or may have not processed none of the messages when your main method terminates the system.

If there are messages in the inbox when an actor is stopped, they will be sent to deadLetters (described in the docs here: http://doc.akka.io/docs/akka/2.4.1/java/untyped-actors.html#Stopping_actors).

So, my guess is that you have placed messages in the inboxes of your actors with the 4 calls to tell but then terminate, and since it is asynchronous it´s not deterministic if your actors have processed the messages yet or not. And as your actors are shutdown, the messages left in the inboxes will be sent to deadLetters.

I'm not sure if there is a final state when your actors are "done" in your example code, so given that, one way to make it work would be to block on for example StdIn.readLine(); and then shutdown the system, this way you can easily try out stuff and decide yourself how long time you want to run your application.

Upvotes: 3

Related Questions