2016-07-22 28 views
0

Ich habe Probleme, Fallklassen innerhalb eines Merkmals zu bekommen, um mit der Akka-Serialisierung zu arbeiten. Der folgende Code funktioniert wie erwartet:scala/akka der Fallklasse mit Merkmal

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 
} 

aber wenn ich die Kommentare zu entfernen, wird eine Ausnahme ausgelöst:

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) 

beim Versuch, den Byte-String deserialisieren. Ich bekomme die Ausnahme, auch nachdem ich versucht habe, relevante Klassen serialisierbar zu machen (wie in den Kommentaren zu sehen).

Hat jemand eine Idee, wie man das funktioniert oder warum es scheitert? Ich benutze Scala 2.11.8 und Akka 2.4.8; Ich baue und teste mit sbt assembly ...

vielen Dank für einen Einblick!

Antwort

1

Der Grund, warum Sie eine Ausnahme erhalten, wenn Sie die Kommentare entfernen ist, dass in diesem Code, um die Klassen machen, die serialisiert werden (Plus, Minus, etc ...) einen Teil der Klasse Foo, wie Sie mischen sie in. Als solche, um diese Klassen zu serialisieren, muss die umschließende Klasse auch serialisiert werden. Deshalb musste man Foo in erster Linie von Serializable erben, was eigentlich die erste rote Flagge hätte sein sollen. Nun sind das Actor-System und die Serialisierungserweiterung Felder auf Foo, so dass der Serialisierungscode auch Dinge benötigt, um sie auch zu serialisieren, wo der Fehler herkommt.

Sie können dies auf verschiedene Arten beheben. Eine wäre, TestProtocol als object zu definieren und dann innerhalb von Foo zu importieren, anstatt es als trait zu mischen. Wenn Sie es beim Mischen in gesetzt sind, dann können Sie Sie Code in etwa so aussehen machen:

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

Hier gibt es keine Felder in Foo, als ich den Schauspieler-System und so nach unten in die run Verfahren geschoben haben . Dies ist nur eine weitere Möglichkeit, Ihr Problem zu umgehen.

+0

Brilliant! Dies ist eine großartige Hilfe und eine ausgezeichnete Beschreibung ... Danke! – jetson