`Map [String,String]`别名的NotSerializableException

时间:2013-07-17 20:52:53

标签: scala exception serialization akka

我正在尝试将一个对象发送给一个远程actor,我得到了这个例外:

ERROR akka.remote.EndpointWriter - Transient association error (association remains live)
java.io.NotSerializableException: scala.collection.immutable.MapLike$$anon$2

被序列化的对象是一个案例类:

case class LocationReport(idn: String, report: String, timestamp: Option[String], location: Attr, status: Attr, alarms: Attr, network: Attr, sensors: Attr) extends Message(idn) {

  val ts = timestamp getOrElse location("fix_timestamp")

  def json =
    (report ->
      ("TIME" -> ts) ~
      ("location" -> location) ~
      ("alarms" -> alarms) ~
      ("network" -> network) ~
      ("sensors" -> ((status ++ sensors) + ("CUSTOMCLOCK" -> Report.decodeTimestamp(ts)))))
}

Attr是一种类型重新定义:

type Attr = Map[String, String]

Message类非常简单:

abstract class Message(idn: String) {
  def topic = idn
  def json(): JValue
}

我想知道类型别名/重定义是否会使序列化程序混乱。我想我正在使用ProtoBuf序列化,但我确实在堆栈跟踪中看到了JavaSerializer

更多调试信息

我新建了一个JavaSerializer并单独序列化了每个地图。只有一个(alarms)无法序列化。这是每个的toString:

这一次失败了:

alarms = Map(LOWBATTERY -> 1373623446000)

这些成功了:

location = Map(a_value -> 6, latitude -> 37.63473, p_value -> 4, longitude -> -97.41459, fix_timestamp -> 3F0AE7FF, status -> OK, fix_type -> MSBL, CUSTOMCLOCK -> 1373644159000)
network = Map(SID -> 1271, RSSI -> 85)
sensors = Map(HUMIDITY -> -999, PRESSURE -> -999, LIGHT -> -999  9:52 AM)
status = Map(TEMPERATURE_F -> 923, CYCLE -> 4, TEMPERATURE1_C -> 335, CAP_REMAINING -> 560, VOLTAGE -> 3691, CAP_FULL -> 3897)

2 个答案:

答案 0 :(得分:29)

问题是Map.mapValues生成了一个不可序列化的对象。创建警报时,它会运行alarms.mapValues(hex2Int)之类的内容。这里描述了问题和解决方法:

https://issues.scala-lang.org/browse/SI-7005

简而言之,解决方案是alarms.mapValues(hex2Int).map(identity)

答案 1 :(得分:0)

不确定这是否适用于所有情况,但我的解决方法只是在序列化之前将地图转换为序列(序列前的.toSeq)。反序列化后,toMap应该为您提供相同的地图。