2016-07-22 65 views
0

我在使用Akka序列化的特征中获取案例类时遇到了困难。下面的代码按预期工作:具有特质的案例类的scala/akka

import akka.actor.ActorSystem 
import akka.serialization.SerializationExtension 

/*trait TestProtocol {*/ 
    sealed abstract class Expr /* extends Serializable */ 
    final case class Literal(v: Double) extends Expr 
    final case class Plus(a: Expr, b: Expr) extends Expr 
    final case class Minus(a: Expr, b: Expr) extends Expr 
    final case class Times(a: Expr, b: Expr) extends Expr 
    final case class Divide(a: Expr, b: Expr) extends Expr 
/*}*/ 

class Foo /* extends Serializable with TestProtocol */ { 
    val system = ActorSystem("snitch") 
    def sample = List(
    Plus(Literal(9),Literal(5)), 
    Times(Plus(Literal(1),Literal(18)),Literal(2)) 
) 
    val serialization = SerializationExtension(system) 
    val serializer = serialization.findSerializerFor(sample) 
    val bytes = serializer.toBinary(sample) 
    val back = serializer.fromBinary(bytes, manifest = None) 
    println(s">>>>>>> pre-serialize: ${sample}") 
    println(s">>>>>>> deserialized: ${back}") 
} 

object Main extends App { 
    val bar = new Foo 
    bar.system.terminate 
} 

,但如果我删除了评论,抛出一个异常:

Exception in thread "main" java.io.NotSerializableException: akka.serialization.Serialization 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184) 
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) 
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) 
    at scala.collection.immutable.List$SerializationProxy.writeObject(List.scala:468) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:483) 
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) 
    at akka.serialization.JavaSerializer$$anonfun$toBinary$1.apply$mcV$sp(Serializer.scala:235) 
    at akka.serialization.JavaSerializer$$anonfun$toBinary$1.apply(Serializer.scala:235) 
    at akka.serialization.JavaSerializer$$anonfun$toBinary$1.apply(Serializer.scala:235) 
    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58) 
    at akka.serialization.JavaSerializer.toBinary(Serializer.scala:235) 
    at buggy.Foo.<init>(Main.scala:22) 
    at buggy.Main$.delayedEndpoint$buggy$Main$1(Main.scala:29) 

尝试反序列化的字节字符串时。即使在我尝试创建任何相关的类可序列化之后,我也会遇到异常(如注释中所示)。

有没有人有任何想法如何使这项工作或为什么失败?我使用的是Scala 2.11.8和Akka 2.4.8;我建立和测试与sbt大会...

非常感谢任何见解!

回答

1

当你删除评论,你会得到一个异常的原因是,在该代码,你这是正在序列化的类(PlusMinus,等...)类Foo的一部分,因为你是混合他们进来。因此,为了序列化这些类,封闭类也必须被序列化。这就是为什么你必须首先从Serializable继承Foo,这应该是第一个红旗。现在,参与者系统和序列化扩展名是Foo上的字段,因此序列化代码也需要对它们进行序列化,这也是故障来自的地方。

您可以通过多种方式解决此问题。一种方法是将TestProtocol定义为object,然后将其导入Foo之内,而不是将其作为trait混入。如果您在混合设置它,那么你可以让你的代码看起来是这样的:

object Main extends App { 
    val bar = new Foo 
    bar.run 
} 

trait TestProtocol { 
    sealed abstract class Expr extends Serializable 
    final case class Literal(v: Double) extends Expr 
    final case class Plus(a: Expr, b: Expr) extends Expr 
    final case class Minus(a: Expr, b: Expr) extends Expr 
    final case class Times(a: Expr, b: Expr) extends Expr 
    final case class Divide(a: Expr, b: Expr) extends Expr 
} 

class Foo extends Serializable with TestProtocol { 

    def run = { 
    val system = ActorSystem("snitch") 
    def sample = List(
     Plus(Literal(9),Literal(5)), 
     Times(Plus(Literal(1),Literal(18)),Literal(2)) 
    ) 
    val serialization = SerializationExtension(system) 
    val serializer = serialization.findSerializerFor(sample) 
    val bytes = serializer.toBinary(sample) 
    val back = serializer.fromBinary(bytes, manifest = None) 
    println(s">>>>>>> pre-serialize: ${sample}") 
    println(s">>>>>>> deserialized: ${back}") 
    system.terminate 
    } 
} 

这里,也有Foo没有字段,因为我已经推了演员系统和这种下降到run方法。这是解决您的问题的另一种方式。

+0

太棒了!这是一个很好的帮助和一个很好的描述......谢谢! – jetson