我无法在特征中获取案例类来使用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程序集构建和测试......
非常感谢任何见解!
答案 0 :(得分:1)
删除注释时出现异常的原因是,在该代码中,您正在使序列化的类(Plus
,Minus
等...)成为你正在混合它们的类Foo
。因此,为了序列化这些类,封闭类也必须序列化。这就是为什么你必须首先从Foo
继承Serializable
,这应该是第一个红旗。现在,actor系统和序列化扩展是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
中没有字段,因为我已经将actor系统推到了run
方法中。这只是另一种解决问题的方法。