user2963977
user2963977

Reputation: 572

Akka persistence NotSerializableException for Enumeration

I'm trying to use akkas persistance module(2.3.0), unfortunately when I'm sending Persistent message containing Enumeration I'm getting java.io.NotSerializableException. Here's my earthy example:

object TestEnum extends Enumeration with Serializable {
  type TestEnum = Value
  val test = Value("test")
}

class TestProcessor extends Processor with Logging {
  override def receive: Actor.Receive = {
    case PersistenceFailure(payload, sequenceNr, cause) =>
      log.error(s"error when reciving persistent message[$payload]", cause)
    case a =>
      log.error(s"test proc recived message [$a]")
  }
}
val a = sys.actorOf(Props[TestProcessor])
a ! Persistent(TestEnum.test)

this ends with

 error when reciving persistent message[test]java.io.NotSerializableException:         scala.slick.driver.JdbcTypesComponent$MappedJdbcType$$anon$1
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
    at akka.serialization.JavaSerializer$$anonfun$toBinary$1.apply$mcV$sp(Serializer.scala:129)
    at akka.serialization.JavaSerializer$$anonfun$toBinary$1.apply(Serializer.scala:129)
    at akka.serialization.JavaSerializer$$anonfun$toBinary$1.apply(Serializer.scala:129)
    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:57)
    at akka.serialization.JavaSerializer.toBinary(Serializer.scala:129)
    at akka.persistence.serialization.MessageSerializer.persistentPayloadBuilder(MessageSerializer.scala:111)
    at akka.persistence.serialization.MessageSerializer.akka$persistence$serialization$MessageSerializer$$persistentMessageBuilder(MessageSerializer.scala:97)
    at akka.persistence.serialization.MessageSerializer.toBinary(MessageSerializer.scala:45)
    at akka.serialization.Serialization$$anonfun$serialize$1.apply(Serialization.scala:90)
    at akka.serialization.Serialization$$anonfun$serialize$1.apply(Serialization.scala:90)
    at scala.util.Try$.apply(Try.scala:161)
    at akka.serialization.Serialization.serialize(Serialization.scala:90)
    at akka.persistence.journal.leveldb.LeveldbStore$class.persistentToBytes(LeveldbStore.scala:98)
    at akka.persistence.journal.leveldb.LeveldbJournal.persistentToBytes(LeveldbJournal.scala:19)
    at akka.persistence.journal.leveldb.LeveldbStore$class.akka$persistence$journal$leveldb$LeveldbStore$$addToMessageBatch(LeveldbStore.scala:104)
    at akka.persistence.journal.leveldb.LeveldbStore$$anonfun$writeMessages$1$$anonfun$apply$1.apply(LeveldbStore.scala:48)
    at akka.persistence.journal.leveldb.LeveldbStore$$anonfun$writeMessages$1$$anonfun$apply$1.apply(LeveldbStore.scala:48)
    at scala.collection.Iterator$class.foreach(Iterator.scala:727)
    at scala.collection.AbstractIterator.foreach(Iterator.scala:1157)
    at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
    at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
    at akka.persistence.journal.leveldb.LeveldbStore$$anonfun$writeMessages$1.apply(LeveldbStore.scala:48)
    at akka.persistence.journal.leveldb.LeveldbStore$$anonfun$writeMessages$1.apply(LeveldbStore.scala:48)
    at akka.persistence.journal.leveldb.LeveldbStore$class.withBatch(LeveldbStore.scala:90)
    at akka.persistence.journal.leveldb.LeveldbJournal.withBatch(LeveldbJournal.scala:19)
    at akka.persistence.journal.leveldb.LeveldbStore$class.writeMessages(LeveldbStore.scala:48)
    at akka.persistence.journal.leveldb.LeveldbJournal.writeMessages(LeveldbJournal.scala:19)
    at akka.persistence.journal.SyncWriteJournal$$anonfun$receive$1$$anonfun$1.apply$mcV$sp(SyncWriteJournal.scala:27)
    at akka.persistence.journal.SyncWriteJournal$$anonfun$receive$1$$anonfun$1.apply(SyncWriteJournal.scala:27)
    at akka.persistence.journal.SyncWriteJournal$$anonfun$receive$1$$anonfun$1.apply(SyncWriteJournal.scala:27)
    at scala.util.Try$.apply(Try.scala:161)
    at akka.persistence.journal.SyncWriteJournal$$anonfun$receive$1.applyOrElse(SyncWriteJournal.scala:27)
    at akka.actor.Actor$class.aroundReceive(Actor.scala:465)
    at akka.persistence.journal.leveldb.LeveldbJournal.aroundReceive(LeveldbJournal.scala:19)
    at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516)
    at akka.actor.ActorCell.invoke(ActorCell.scala:487)
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:238)
    at akka.dispatch.Mailbox.run(Mailbox.scala:220)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

anybody has any idea what is going on here and how to fix it?

Upvotes: 3

Views: 1184

Answers (1)

user2963977
user2963977

Reputation: 572

It was more complicated that I thought. According to Patrik suggesstion I've defined all participating objects as top level classes/objects in different files. And test example started to work. Finally I've discovered why error occurs:

I'm using slick to communicate with my DB so I've declared very useful Enumeration base class with default mapper that allows slick to use Enumeration without writing converters

abstract class DBEnum extends Enumeration {
  implicit val enumMapper = MappedJdbcType.base[Value, String](_.toString, this.withName(_))
}

Then I've derived from that class and created

object AccountType extends DBEnum{
  type AccountType = Value
  val ADMINISTRATOR = Value("administrator")
  val REGULAR = Value("regular")
  val ADMINISTRATOR_SPONSORED = Value("administrator_sponsored")
}

my actual test example was

a ! Persistent(TestEnum.test)
a ! Persistent(AccountType.ADMINISTRATOR)

and it seems that TestEnum started to have enumMapper(probably because of some weird implicit conversion - maby someone can explain how is it possible) which can't be serialized(it does not implement serializable).

changing

implicit val enumMapper = MappedJdbcType.base[Value, String](_.toString, this.withName(_))

to

implicit def enumMapper = MappedJdbcType.base[Value, String](_.toString, this.withName(_))

fixed my problem.

Upvotes: 2

Related Questions