1
votes

I am looking for an example of how to use Akka's pattern Patterns.askWithReplyTo using Java.

A sample project is available at Github: https://github.com/pcdhan/akka-patterns.git

My challenge is I am unable to include sender's ActorRef in the payload.

A Local Actor

ActorRef localA= system.actorOf(LocalActor.props(), "localA");

A Remote Actor

Timeout timeout = new Timeout(10000, TimeUnit.MILLISECONDS);
ActorSelection actorSelection=system.actorSelection("akka.tcp://ClusterSystem@localhost:2551/user/ActorA");
Future<Object> future = Patterns.ask(actorSelection, new Identify(""), timeout);
ActorIdentity reply = (ActorIdentity) Await.result(future, timeout.duration());
ActorRef actorRef = reply.ref().get(); //my remote actor ref

Send A payload to Remote Actor along with ActorRef (localA)

Payload payload = new Payload(); //How do I pass localA here
payload.setMsg("0");
Future<Object> askWithSenderRef = 
Patterns.askWithReplyTo(actorRef,payload,20000L);
Payload responsePayload = (Payload) Await.result(askWithSenderRef, 
timeout.duration());
System.out.println("Response from Remote Actor Payload: "+responsePayload.getMsg());

Payload

public class Payload implements Function<ActorRef, Object>, Serializable {
private static final long serialVersionUID = 1L;

String msg;

public String getMsg() {
    return msg;
}

public void setMsg(String msg) {
    this.msg = msg;
}

@Override
public Object apply(ActorRef param) throws Exception {
    return this;
}

}

Remote Actor logs

...Actor[akka.tcp://ClusterSystem@localhost:53324/temp/$d]
...Actor[akka.tcp://ClusterSystem@localhost:53324/temp/$e]

I expect .../user/localA, but I get /temp/$d

1

1 Answers

1
votes

askWithReplyTo is not meant to pass the sending actor self into the message.

askWithReplyTo expects that you give it a factory function, which get fed the temporary response actor, so if you have a message that you could construct like so:

new MyMessage(ActorRef replyTo)

You could use that with askWithReplyTo like so:

final Future<Object> f = Patterns.askWithReplyTo(
  otherActor,
  replyTo -> new MyMessage(replyTo),
  timeout);

The second parameter is a lambda which will be invoked with the temporary ask-actor (which is always created when you do ask to take care of the response timeout) so that you can include it in the message.

The pattern is only useful when the receiving side uses that replyTo field to respond and not sender(), which is what you'd usually do to respond.