SkyWalker
SkyWalker

Reputation: 14309

How to pass remote references between Akka actors?

I have three remote Akka actors: A, B and C. A sends a message to B and B saves A's reference (see below). In addition, I need B to send A's reference to C. How can I do that? The Java code for B looks like this:

public class B extends UntypedActor {
    //---------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public void onReceive(Object object) throws Exception {
        if (refA == null) {
            refA = getSender();
        }

        // how do I send refA to C???
        refC.tell(refA, getSelf()); // <== like this?
    }

    // set during onReceive
    private ActorRef refA = null;

    // initialized in constructor
    private final ActorRef refC;
}

I just checked and ActorRef is Serializable so in theory my solution proposed above should work but is there a different/official/cleaner way to do it?

Upvotes: 1

Views: 1281

Answers (2)

Didac Montero
Didac Montero

Reputation: 2086

If actor C only needs to have a reference to actor A, you only need to change the line in Actor B with the tell method to:

refC.tell(refA, getSender()); 

If actor C must have a reference of both, Actor A and Actor B, then you can do two things:

1) Use the code you provided.

2) Use the method getContext().actorSelection("actor_name") in the Actor C to fetch the Actor A. How actorSelection works is described in the Akka Documentation but it will look as follows:

public class ActorC extends UntypedActor {
    private static String ID="whateverID";
    private ActorRef actorA;
    {
      getContext().actorSelection("akka.tcp://app@host:port/user/actorAName").
      tell(new Identify(ID), getSelf());
    }
    //As an alternative, if you need the ActorA initialized in the constructor,
    //you can use the .resolveOne method.
    //public ActorC(){
    //    super();
    //    Timeout timeout=new Timeout(4, TimeUnit.SECONDS);
    //      try {
    //          httpProducer=Await.result(getContext().actorSelection("akka.tcp://app@host:port/user/actorAName").resolveOne(timeout), timeout.duration());
    //      } catch (Exception e) {
    //      Logger.error("Error fetching the routerHTTProducer");
    //      }
    //}
    @Override
    public void onReceive(Object m) throws Exception {
        if (m instanceof ActorIdentity) {
            ActorIdentity identity = (ActorIdentity) m;
            if (identity.correlationId().equals(ID) && identity.getRef() != null) {
                actorA= identity.getRef();
            }           
        }
        //else if (m instanceof ...){}  
    }
}    

Upvotes: 2

yǝsʞǝla
yǝsʞǝla

Reputation: 16412

Your solution looks fine and is a common thing to do. Akka references designed to be location transparent and serializable. Thus you can send Actor references to remote clients and they'll just use them without any additional setup.

Upvotes: 4

Related Questions