I am trying to implement a basic broadcast router in which the routees are on remote machines.
The code is as follows :
localApp.conf
akka {
log-dead-letters = 10
log-dead-letters-during-shutdown = off
actor {
provider = "akka.remote.RemoteActorRefProvider"
serialize-messages = on
serializers {
java = "akka.serialization.JavaSerializer"
}
serialization-bindings {
"java.lang.String" = java
"test.akkaLocal.LocalWrapper" = java
}
deployment {
/LocalMaster/broadcastRouter {
router = "broadcast"
nr-of-instances = 1
target {
nodes = ["akka.tcp://RemoteApp@127.0.0.1:10175"]
}
}
}
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
netty {
tcp {
hostname = "127.0.0.1"
port = 10174
}
}
}
}
LocalApp.java
public class LocalApp
{
public static void main(String[] args)
{
LocalApp app = new LocalApp();
app.executeLocal();
}
private void executeLocal() {
ActorSystem system = ActorSystem.create("LocalApp", ConfigFactory.load("localApp"));
final ActorRef master = system.actorOf(Props.create(LocalMaster.class), "LocalMaster");
master.tell(new LocalWrapper.Execute(), ActorRef.noSender());
}
public static class LocalMaster extends UntypedActor {
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof LocalWrapper.Execute) {
ActorSelection remoteActor =
getContext().actorSelection("akka.tcp://RemoteApp@127.0.0.1:10175/user/RemoteMaster");
ActorRef remoteRouter = getContext().actorOf(
Props.create(RemoteActor.class).withRouter(new FromConfig()), "broadcastRouter");
String msg = "Hello";
// remoteActor.tell(msg, getSelf());
remoteRouter.tell(msg, getSelf());
} else if (message instanceof String) {
String response = (String) message;
System.out.println(response);
}
}
}
public static class RemoteActor extends UntypedActor {
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof String) {
String msg = (String) message;
System.out.println(msg);
String resp = "World";
getSender().tell(resp, getSelf());
}
}
}
}
In the remoteApp.conf, the port is given as 10175
RemoteApp.java
public class RemoteApp
{
public static void main(String[] args)
{
RemoteApp app = new RemoteApp();
app.executeRemote();
}
private void executeRemote() {
ActorSystem system = ActorSystem.create("RemoteApp", ConfigFactory.load("remoteApp"));
system.actorOf(Props.create(RemoteMaster.class), "RemoteMaster");
}
public static class RemoteMaster extends UntypedActor {
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof String) {
String msg = (String) message;
System.out.println(msg);
String response = "World";
getSender().tell(response, getSelf());
}
}
}
}
Now I am not able to understand concept of remote routing. Does it deploy a local actor on remote machines and then send messages to them, or connect to remote actors on remote machines and then send messages to them ?
Using my code, I am able to send simple messages to the remote machine ( using actor selection ) the remoteActor.tell(msg, getSelf()) ( commented code ) in the LocalApp sends and receives messages and doesn't give any error.
But When I create the router using local Actor, I get dead letter errors.
[INFO] [02/04/2014 16:34:58.408] [RemoteApp-akka.actor.default-dispatcher-4] [akka://RemoteApp/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2FLocalApp%40127.0.0.1%3A10174-0/endpointWriter/endpointReader-akka.tcp%3A%2F%2FLocalApp%40127.0.0.1%3A10174-0]
Message [akka.remote.transport.AssociationHandle$InboundPayload] from Actor[akka://RemoteApp/deadLetters] to Actor[akka://RemoteApp/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2FLocalApp%40127.0.0.1%3A10174-0/endpointWriter/endpointReader-akka.tcp%3A%2F%2FLocalApp%40127.0.0.1%3A10174-0#-288427524] was not delivered.
[1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
Can someone tell me what I am doing wrong ?
---------UPDATE----------
I Found out the problem. The remote and local classes were in different projects. During basic communication between the local and remote project, String was the type of the object transferred, that why it was successful. Is there a way to transfer objects of custom classes between two different projects ? I tried implementing Serializable and adding it to the conf file but it doesn't make a difference