Now I am learning Akka a little bit, but I can't understand the exact meaning of getSender()
.
In this official document, the method getSender()
is used and the explanation is like
// Reply to original sender of message
getSender().tell(msg + ":" + getSelf());
This seems to be a response method, so this actor has to respond to a actor who sent a message and that method is what does it actually. And I am confused because I don't understand whether getSender()
affords the receiver actor or the sender actor. So, could you give me an explanation about it?
Thanks.
public class WebSocketActor extends UntypedActor {
/**
* Actor's reference
*/
private final static ActorRef ref = Akka.system().actorOf(new Props(WebSocketActor.class));
/**
* the list of those who should get messages
*/
Map<String, WebSocket.Out<JsonNode>> members = new HashMap<String, WebSocket.Out<JsonNode>>();
/**
* a method adding a certain user
* @param username a user name
* @param in receive of WebSokcet
* @param out sending of WebSocket
* @throws Exception
*/
public static void join(final String username, WebSocket.In<JsonNode> in, WebSocket.Out<JsonNode> out) throws Exception {
// causing JOIN event
Boolean result = (Boolean) Await.result(ask(ref, new Message(username, "", "", WebSocketEvent.JOIN, out), 1000), Duration.create(1, SECONDS));
if(result) {
// if a message is sent,MESSAGE event will occur.
in.onMessage(new Callback<JsonNode>() {
public void invoke(JsonNode event) {
ref.tell(new Message(username, event.get("x").asText(), event.get("y").asText(), WebSocketEvent.MESSAGE, null), ref);
}
});
// a close method when WebSocket is closed
in.onClose(new Callback0() {
public void invoke() {
ref.tell(new Message(username, "", "", WebSocketEvent.QUIT, null), ref);
}
});
} else {
// sending an error
ObjectNode error = Json.newObject();
error.put("error", result);
out.write(error);
}
}
/**
* the executable method when an event happens
* @param message an event object
* @throws Exception
*/
@Override
public void onReceive(Object message) throws Exception {
// diciding whether the object is an event or not
Option<Message> event = EventUtil.getEvent(message);
if(event.isDefined()){
Message m = event.get();
switch (m.getEventType()) {
// adding to members
case JOIN:
members.put(m.getUsername(), m.getChannel());
getSender().tell(true, ref);
break;
// sending all
case MESSAGE:
WebSocketMessenger.notifyAll(m.getUsername(), m.getX(), m.getY(), members);
break;
// excluding someone from members
case QUIT:
members.remove(m.getUsername());
break;
default:
unhandled(message);
break;
}
}
}
}
In above code, in onReceive(Object message)
method you can see the getSender()
method. However, when the join(final String username, WebSocket.In<JsonNode> in, WebSocket.Out out)
method is called, first the actor asks a new message of another actor, and then in onReceive(Object message)
method, another actor answers with true
by executing like getSender().tell(true, ref);
. In this circumstance, getSender()
gives the first actor who asked. Isn't it strange because the first actor who asked gives true
to the another actor who should give true
to the first actor?
Your answer would be very useful, but I am still not clear, sorry.
EDIT:
You said this doesn't work well, but it works.
Are you familiar with PlayFramework? If so, it is totally straightforward to grasp a whole picture. This code is the controller's code which calls the join()
method.
public static WebSocket<JsonNode> ws() {
final String username = session("username");
return new WebSocket<JsonNode>() {
@Override
public void onReady(final WebSocket.In<JsonNode> in, final WebSocket.Out<JsonNode> out) {
try {
WebSocketActor.join(username, in, out);
} catch (Exception e) {
Logger.error("Can't connect WebSocket");
e.printStackTrace();
}
}
};
}