2016-07-22 68 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