I have two projects. First is written in Java and uses Akka whereas the second one is a Scala project and it makes use of Akka actors as well. I've established a successful connection between the two in terms of sending common objects and fields(i.e String). What I want is be able to send custom Objects such as User in between. Thus, Java side would simply have entities, and the Scala side would have Case classes respectively.
1.User.java:
public class User implements Serializable {
public final String name;
public User(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [name=" + name + "]";
}
}
2.Hello App class:
public class Boot {
public static void main(String[] args) {
ActorSystem system;
ActorSelection remoteActor;
Config config = ConfigFactory.load().getConfig("hello");
system = ActorSystem.create("HelloApplication");
String remoteAcPath = config.getString("remote-user-actor");
remoteUserHandleActor = system.actorSelection(remoteAcPath);
User u = new User("Alex");
System.out.println("Sending message to Remote Actor ...");
remoteUserHandleActor.tell(u, userActor);
}
}
1.User case class:
case class User(val name: String) extends Serializable
2.Hello App:
object Boot extends App {
implicit val ec = ExecutionContext
implicit val timeout = Timeout(5 seconds)
lazy implicit val config: Config = ConfigFactory.load
val system = ActorSystem("HelloServer")
val userActor = system.actorOf(Props[UserHandleActor], name = "userHandlerActor")
}
Sending a message with Java actor to Scala actor casues following dead letters error in Java side:
[HelloApplication-akka.actor.default-dispatcher-15] INFO akka.actor.LocalActorRef - Message [akka.remote.transport.AssociationHandle$Disassociated] from Actor[akka://HelloApplication/deadLetters] to Actor[akka://HelloApplication/system/transports/akkaprotocolmanager.tcp0/akkaProtocol-tcp%3A%2F%2FHelloServer%40127.0.0.1%3A1111-1#-1775289115] 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'.
[HelloApplication-akka.actor.default-dispatcher-5] INFO akka.actor.LocalActorRef - Message [akka.remote.transport.ActorTransportAdapter$DisassociateUnderlying] from Actor[akka://HelloApplication/deadLetters] to Actor[akka://HelloApplication/system/transports/akkaprotocolmanager.tcp0/akkaProtocol-tcp%3A%2F%2FHelloServer%40127.0.0.1%3A1111-1#-1775289115] was not delivered. [2] 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'.
Scala side shows this message:
31/10/2013 09:04:38 UTC | DEBUG | Remoting HelloServer-akka.actor.default-dispatcher-3 - Associated [akka.tcp://[email protected]:1111] <- [akka.tcp://[email protected]:2552]
31/10/2013 09:04:38 UTC | DEBUG | akka.remote.EndpointWriter HelloServer-akka.actor.default-dispatcher-3 - Disassociated [akka.tcp://[email protected]:1111] <- [akka.tcp://[email protected]:2552]
31/10/2013 09:04:38 UTC | INFO | akka.actor.LocalActorRef HelloServer-akka.actor.default-dispatcher-5 - Message [akka.remote.transport.AssociationHandle$Disassociated] from Actor[akka://HelloServer/deadLetters] to Actor[akka://HelloServer/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2FHelloApplication%40192.162.1.4%3A2552-0/endpointWriter/endpointReader-akka.tcp%3A%2F%2FHelloApplication%40192.162.1.4%3A2552-0#526150656] 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'.
31/10/2013 09:04:38 UTC | INFO | akka.actor.LocalActorRef HelloServer-akka.actor.default-dispatcher-5 - Message [akka.remote.transport.AssociationHandle$Disassociated] from Actor[akka://HelloServer/deadLetters] to Actor[akka://HelloServer/system/transports/akkaprotocolmanager.tcp0/akkaProtocol-tcp%3A%2F%2FHelloServer%40127.0.0.1%3A54194-1#-802595184] was not delivered. [2] 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'.
31/10/2013 09:04:38 UTC | DEBUG | akka.remote.EndpointWriter HelloServer-akka.actor.default-dispatcher-6 - Associated [akka.tcp://[email protected]:1111] -> [akka.tcp://[email protected]:2552]
31/10/2013 09:04:38 UTC | DEBUG | Remoting HelloServer-akka.actor.default-dispatcher-3 - Associated [akka.tcp://[email protected]:1111] <- [akka.tcp://[email protected]:2552]
Afterwards, I came up with a crazy idea that I set the same serialVersionUID (i.e. serialVersionUID = 888L) to User.java entity and User case class, and interestingly, messages are successfully handled and everything is fine. I know that at this point I am doing wrong with that serialization.
1) What is the best bet of achieving my goal?
2) If there are ways of converting custom objects between Java and Scala (I know of javaconversions which is for collections and the like) that will be super.
3) Is my crazy idea of setting the same serialVersionUID in both sides proper?
One option is to use Java classes in both projects and provide some layer over them so that they can be used in Scala almost like they were case classes.
For example, assuming you only have a Java version of User class, you can do this on the Scala side:
object User {
// will allow you to create User instances without the 'new' keyword
def apply(name: String) =
new User(name)
// will allow you to pattern-match against User instances, for example in
// actor's 'receive' function
def unapply(user: User) =
Some(user.name)
// implicit wrapper that will add some Scala-like API to your User class
implicit class UserScalaApi(user: User) {
// whatever you need here (the 'copy' method, etc.)
}
}
The downside of this is that you have to create such adaptation layer for every Java class (macro annotations would be so awesome here...).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With