Akka EventSourced Actor序列化报错:无法实例化内部类State
问题:Jackson序列化Typed EventSourced Actor状态时出错
在尝试持久化事件并更新Actor状态时,抛出如下异常:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `module.MyActor$State`: non-static inner classes like this can only by instantiated using default, no-argument constructor
相关Actor代码如下:
object MyActor { final case class Settings( name: String = "", accessToken: AccessToken = AccessToken() ) extends CborSerializable . . . } class MyActor()(implicit system: ActorSystem[_]) { import MyActor._ private implicit val executionContext: ExecutionContextExecutor = system.executionContext private val sharding = ClusterSharding(system) // State final case class State( settings: Settings = Settings(), pollTime: Long = 0L ) extends CborSerializable . . private def onEvent(state: State, event: Event): State = { event match { case _ => { state.copy(pollTime = state.pollTime.updated(timestampToStringDate(System.currentTimeMillis()))) } } . . }
这是一个Typed EventSourced Actor,事件/命令处理程序因与序列化问题无关已省略。
使用Jackson序列化器,application.conf配置如下:
akka.actor.serialization-bindings { "module.CborSerializable" = jackson-cbor }
模块中已定义trait CborSerializable,需排查操作错误点。
解决方案
问题核心:State是MyActor类的非静态内部类,Jackson反序列化时无法正确构造这类实例——非静态内部类必须依赖外部MyActor实例才能创建,但反序列化场景下没有可用的外部实例,即便提供默认无参构造器也无法解决。
修复方法二选一:
- 将
State移到MyActor的伴生对象object MyActor内部,此时它会成为静态嵌套类(Scala中伴生对象内的类不依赖外部类实例) - 直接把
State定义为顶层类(放在当前文件最外层或单独文件中)
调整后的代码示例(将State移至伴生对象):
object MyActor { final case class Settings( name: String = "", accessToken: AccessToken = AccessToken() ) extends CborSerializable // 把State移到伴生对象内,转为静态嵌套类 final case class State( settings: Settings = Settings(), pollTime: Long = 0L ) extends CborSerializable . . . } class MyActor()(implicit system: ActorSystem[_]) { import MyActor._ private implicit val executionContext: ExecutionContextExecutor = system.executionContext private val sharding = ClusterSharding(system) . . private def onEvent(state: State, event: Event): State = { event match { case _ => { state.copy(pollTime = state.pollTime.updated(timestampToStringDate(System.currentTimeMillis()))) } } . . }
调整后State成为独立的静态类,Jackson可通过无参构造器正常完成序列化与反序列化操作。
内容的提问来源于stack exchange,提问作者Arpit Sharma
相关产品推荐
相关产品推荐

