I started to learn Akka and downloaded example from official guid:
I didn't understand tell
method second argument usage:
In main method written:
howdyGreeter.tell(new WhoToGreet("Akka"), ActorRef.noSender());
Thus second argument is ActorRef.noSender()
on actor side entry point looks like this:
@Override
public Receive createReceive() {
return receiveBuilder()
.match(WhoToGreet.class, wtg -> {
this.greeting = message + ", " + wtg.who;
})
.match(Greet.class, x -> {
//#greeter-send-message
printerActor.tell(new Greeting(greeting), getSelf());
//#greeter-send-message
})
Thus I can't have access to passed reference.
Additionally you can see that this actor send message to another actor in case of message type is Greet.class
printerActor.tell(new Greeting(greeting), getSelf());
Here second argument is getSelf()
but I tried to change it with ActorRef.noSender()
and behaviour was not changed.
printer actor entry point looks like this:
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Greeting.class, greeting -> {
log.info(greeting.message);
})
.build();
}
Thus it just prints provided message
printerActor.tell(new Greeting(greeting), getSelf());
Here second argument is
getSelf()
but I tried to change it withActorRef.noSender()
and behaviour was not changed.
The second argument to the tell()
method is the sender reference to which the recipient actor can send a reply. In other words, if actor A sends a message to actor B with getSelf()
as the second argument to a tell()
call, then actor B can use getSender()
to obtain a reference to actor A. Passing ActorRef.noSender()
as the second argument is appropriate when the recipient actor doesn't need a reference to the sender. Note that you can use any ActorRef
as the second argument to tell()
.
The printer actor in the quickstart guide doesn't call getSender()
when it receives a Greeting
message. The only thing that the printer actor does when it receives a Greeting
message is log the greeting. That being the case, it would make more sense for the greeter actor to use ActorRef.noSender()
instead of getSelf()
(but, again, in this case it makes no difference because the printer actor doesn't call getSender()
):
printerActor.tell(new Greeting(greeting), ActorRef.noSender());
If you want to see how the sender reference could be used, you could change the printer actor's behavior:
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Greeting.class, greeting -> {
log.info(greeting.message);
getSender().tell(new PrinterAck(), ActorRef.noSender());
})
.build();
}
Then change the greeter actor to handle a PrinterAck
message (obviously you would need to define a PrinterAck
class):
@Override
public Receive createReceive() {
return receiveBuilder()
.match(WhoToGreet.class, wtg -> {
this.greeting = message + ", " + wtg.who;
})
.match(Greet.class, x -> {
printerActor.tell(new Greeting(greeting), getSelf());
})
.match(PrinterAck.class, x -> {
log.info("Received an ack from the printer actor.");
})
.build();
}