3

我有两个项目。第一个是用 Java 编写的并使用 Akka,而第二个是一个 Scala 项目,它也使用了 Akka actor。String在发送公共对象和字段(即)方面,我已经在两者之间建立了成功的连接。Object我想要的是能够User在两者之间发送 custom 。因此,Java 端将仅具有实体,而 Scala 端将Case classes分别具有。

爪哇:

1.用户.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")
}

使用 Java 演员向 Scala 演员发送消息会导致 Java 端出现死信错误:

[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

4

1 回答 1

2

一种选择是在两个项目中都使用 Java 类,并在它们之上提供一些层,以便它们可以在 Scala 中使用,就像它们是案例类一样。

例如,假设您只有一个 Java 版本的User类,您可以在 Scala 端执行此操作:

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.)
  }
}

这样做的缺点是您必须为每个 Java 类创建这样的适配层(宏注释在这里会非常棒......)。

于 2013-11-01T11:47:26.803 回答