I'm trying to send an object to a remote actor and I got this exception:
ERROR akka.remote.EndpointWriter - Transient association error (association remains live)
java.io.NotSerializableException: scala.collection.immutable.MapLike$$anon$2
The object being serialized is a case class:
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)))))
}
And Attr
is a type re-definition:
type Attr = Map[String, String]
The Message
class is pretty simple:
abstract class Message(idn: String) {
def topic = idn
def json(): JValue
}
I'm wondering if the type alias/redefinition is confusing the serializer. I think I'm using ProtoBuf serialization, but I do see JavaSerializer
in the stacktrace.
More Debugging Info
I newed up a JavaSerializer and individually serialized each of the Maps. Only one (alarms
) fails to serialize. Here's the toString of each of them:
This one failed:
alarms = Map(LOWBATTERY -> 1373623446000)
These succeeded:
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)
The problem is that Map.mapValues
produces an object that's not serializable. When alarms was created, it's run through something like alarms.mapValues(hex2Int)
. The problem and workaround is described here:
https://issues.scala-lang.org/browse/SI-7005
In short, the solution is to do alarms.mapValues(hex2Int).map(identity)
Not sure whether this works in all cases but my workaround was simply to convert the map into a sequence (just .toSeq
before the sequence) before serialization. toMap
should give you the same map after deserialization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With