2016-07-22 14 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の一部を作っているということですしたがって、これらのクラスをシリアライズするには、囲むクラスもシリアル化する必要があります。だから、Fooを最初にSerializableから継承する必要がありました。これは最初の赤旗だったはずです。さて、アクターシステムとシリアライゼーション拡張はFooのフィールドです。シリアライゼーションコードもシリアライズする必要があります。これはエラーの原因です。

これはいくつでも修正できます。 1つはTestProtocolobjectと定義してからとして混ぜるのではなく、Fooの内部にインポートすることです。あなたはそれを混合に設定されている場合、あなたはこのような何かに見えるコーディングすることができます:ここでは

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

を私はrun方法にダウンアクター・システムと、そのようなをプッシュしているとして、フィールドは、Fooではありません。これはあなたの問題を回避するためのもう一つの方法です。

+0

ブリリアント!これは大きな助けと素晴らしい説明です...ありがとう! – jetson

関連する問題