2016-07-22 5 views
0

У меня возникли проблемы с получением классов предметов в пределах черты для работы с серией Akka. Следующий код работает, как ожидалось:scala/akka класса case с признаком

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

Причины вы получите исключение при удалении комментариев является то, что в этом коде, вы делаете классы, которые сериализация (Plus, Minus, и т.д ...) часть класса Foo, как вы смешиваете их в. Таким образом, чтобы сериализовать эти классы, класс включения также должен быть сериализован. Вот почему вы должны были сделать Foo наследовать от Serializable, в первую очередь, это должен был быть первый красный флаг. Теперь система актеров и расширение сериализации являются полями на 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