Incorrect work became

Hello.I use code(work with 2.5.12) from official documentation

public class HotSwapActor extends AbstractActor {
private AbstractActor.Receive angry;
private AbstractActor.Receive happy;


public HotSwapActor() {
	angry = receiveBuilder().matchEquals("foo", s -> {
		getSender().tell("I am already angry?", getSelf());
	}).matchEquals("bar", s -> {
		getContext().become(happy);
	}).matchAny(System.out::println)
	.build();

	happy = receiveBuilder().matchEquals("bar", s -> {
		getSender().tell("I am already happy :-)", getSelf());
	}).matchEquals("foo", s -> {
		getContext().become(angry);
	}).build();
}

@Override
public Receive createReceive() {
	return receiveBuilder().matchEquals("foo", s -> getContext().become(angry))
			.matchEquals("bar", s -> getContext().become(happy)).build();
}


} 

But, if I try

ActorRef secondRef = system.actorOf(Props.create(HotSwapActor.class), "TestHotSwap");
secondRef.tell("foo",ActorRef.noSender());
secondRef.tell("foo",ActorRef.noSender());`

then I give:

[INFO] [04/17/2018 17:33:15.441] [testSystem-akka.actor.default-dispatcher-3] [akka://testSystem/deadLetters] Message [java.lang.String] from Actor[akka://testSystem/user/TestHotSwap#553242136] to Actor[akka://testSystem/deadLetters] 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'.

If I try :

ActorRef secondRef = system.actorOf(Props.create(HotSwapActor.class), "TestHotSwap"); 
secondRef.tell("foo",ActorRef.noSender()); 
secondRef.tell("foo",secondRef);

then all OK…Why?

You should see the dead letter message for both samples, since you are using ActorRef.noSender() in both of the sample snippets. This is because when there is no sender, and an actor tries to reply to the sender, the message ends up in deadletters and will be logged as you have seen.

For the second tell in the second snippet, where you provide the ActorRef to the actor itself as sender it will respond with the “I am already angry?” message to itself, which then should end up in the matchAny and be printed directly to stdout.

secondRef.tell(“foo”,secondRef)
Is it correct?

I don’t think there is a “correct” in this sample, if you want the answers to go to the actor itself, that is correct, if you want the answers to go to dead letter using ActorRef.noSender() is correct.

In most use cases you would likely be inside another actor, and then you would use the actor self as sender, so that replies comes back. In some other cases you want the reply to go to another actor, and in those cases you’d pass an ActorRef to that actor as sender.