【发布时间】:2013-10-31 10:02:13
【问题描述】:
我有两个项目。第一个是用 Java 编写并使用 Akka,而第二个是 Scala 项目,它也使用了 Akka actor。在发送公共对象和字段(即String)方面,我已经在两者之间建立了成功的连接。我想要的是能够在两者之间发送自定义Objects,例如User。因此,Java 端将仅具有实体,而 Scala 端将分别具有Case classes。
Java:
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 类:
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.用户案例类:
case class User(val name: String) extends Serializable
2.你好应用:
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")
}
向 Scala Actor 发送带有 Java Actor 的消息会导致 Java 端出现 dead letters 错误:
[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 端显示此消息:
31/10/2013 09:04:38 UTC | DEBUG | Remoting HelloServer-akka.actor.default-dispatcher-3 - Associated [akka.tcp://HelloServer@127.0.0.1:1111] <- [akka.tcp://HelloApplication@192.162.1.4:2552]
31/10/2013 09:04:38 UTC | DEBUG | akka.remote.EndpointWriter HelloServer-akka.actor.default-dispatcher-3 - Disassociated [akka.tcp://HelloServer@127.0.0.1:1111] <- [akka.tcp://HelloApplication@192.162.1.4: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://HelloServer@127.0.0.1:1111] -> [akka.tcp://HelloApplication@192.162.1.4:2552]
31/10/2013 09:04:38 UTC | DEBUG | Remoting HelloServer-akka.actor.default-dispatcher-3 - Associated [akka.tcp://HelloServer@127.0.0.1:1111] <- [akka.tcp://HelloApplication@192.162.1.4:2552]
之后,我想出了一个疯狂的想法,我将相同的serialVersionUID(即serialVersionUID = 888L)设置为 User.java 实体和 User case 类,有趣的是,消息处理成功,一切都很好。我知道此时我在序列化方面做错了。
1) 实现我的目标的最佳选择是什么?
2) 如果有在 Java 和 Scala 之间转换自定义对象的方法(我知道 javaconversions 用于集合等),那就太好了。
编辑
3) 我的疯狂的想法在两边设置相同的serialVersionUID 正确吗?
【问题讨论】:
-
我会在一个共享的 java 项目中引入 DTO,你的 scala 和 java 应用程序都应该使用它们来传输数据。
-
@mr.boyfox 对,我也不想在 scala 项目中使用 java 类。那不是另一种方式吗? ——
-
我在这里看不到任何其他“架构上干净”的选择。还要考虑重构和可维护性。什么可以保证您的 java 和 scala 类始终保持同步?
-
很多人说写自己的序列化器类(并使用google protobuf),但这是否正确
-
编写自己的序列化程序并使用 protobuf 或类似方法是一种可能的解决方案。如前所述,共享 Java 类是另一种解决方案。