Reputation: 119
In Java, using Akka, I have a Main class which creates two actors (ActorA and ActorB). I can send messages from Main to the Actors, but how do I send messages between the two actors.
Main.java:
public class Main {
public static void main(String[] args) {
// Create the ‘actorTest’ actor system.
final ActorSystem system = ActorSystem.create("actorTest");
// Create the actors.
ActorRef ActorRefA = system.actorOf(Props.create(ActorA.class));
ActorRef ActorRefB = system.actorOf(Props.create(ActorB.class));
// Send a message to ActorA.
ActorRefA.tell("message A", ActorRefA);
}
}
ActorA.java:
public class ActorA extends UntypedActor {
@Override
public void onReceive(Object message) throws Exception {
System.out.println("ActorA received: " + message);
// This is the line which I can't get to work:
ActorRefB.tell("message B", self());
}
}
As you've probably guessed I'm new to this, so any helpful links will be gratefully received. Thanks.
Upvotes: 2
Views: 1356
Reputation: 1761
Assuming the actors both need to know about each other you have a couple of options that spring to mind:
ActorRef
of each actor into the other by passing a message from Main to each with the other's ActorRef
ActorA
and ActorB
explicit names and sending a message to the other actor using their ActorPath
sOption 1
After creation of ActorA and ActorB in main, send the ActorRef
of each to the other e.g.
public class Main {
public static void main(String[] args) {
// Create the ‘actorTest’ actor system.
final ActorSystem system = ActorSystem.create("actorTest");
// Create the actors.
ActorRef ActorRefA = system.actorOf(Props.create(ActorA.class));
ActorRef ActorRefB = system.actorOf(Props.create(ActorB.class));
// Inject ActorRefs
ActorRefA.tell(ActorRefB, ActorRef.noSender());
ActorRefB.tell(ActorRefA, ActorRef.noSender());
// Send a message to ActorA.
ActorRefA.tell("message A", ActorRefA);
}
}
You will also need your ActorA
and ActorB
implementations to handle a message of this type e.g.
public class ActorA extends UntypedActor {
private ActorRef actorRefB;
@Override
public void onReceive(Object message) throws Exception {
System.out.println("ActorA received: " + message);
if (message instanceof ActorRef) {
actorRefB = message;
} else if (message instanceof String) {
// This is the line which I can't get to work:
actorRefB.tell("message B", self());
}
}
}
You would obviously want more sophisticated checks on the variables and sequencing of events to prevent errors but hopefully you get the jist of it.
Option 2
If you name your actors explicitly on creation then you will be able to address them more reliably at their ActorPath
using ActorSelection
Your Main class would become:
public class Main {
public static void main(String[] args) {
// Create the ‘actorTest’ actor system.
final ActorSystem system = ActorSystem.create("actorTest");
// Create the actors.
ActorRef ActorRefA = system.actorOf(Props.create(ActorA.class), "actorA");
ActorRef ActorRefB = system.actorOf(Props.create(ActorB.class), "actorB");
// Send a message to ActorA.
ActorRefA.tell("message A", ActorRefA);
}
}
And then in your ActorA you would use the Actor Selection to address the other actor e.g.
public class ActorA extends UntypedActor {
@Override
public void onReceive(Object message) throws Exception {
System.out.println("ActorA received: " + message);
ActorSelection actorB = getContext().actorSelection("../actorB");
actorB.tell("message B", self());
}
}
It should be noted that there are no guarantees when using Actor Selection that the actor you're addressing actually exists. If you need that then see the following link for details of how to achieve it: http://doc.akka.io/docs/akka/2.4.2/java/untyped-actors.html#Identifying_Actors_via_Actor_Selection
Upvotes: 1