Trying to migrate our codebase to Akka-2.6-M3. Main motivation is to switch to official JacksonSerializer (from existing kryo based implementation).
We have a large set of domain model which is shared with the Scala.js based frontend clients. These models are also used in the messages which go around in Akka-Cluster. Many of the models are sealed trait hierarchies (ADTs).
Going through the JacksonSerializer docs, I see that each ADT must be marked with jackson library annotations like JsonTypeInfo and JsonSubTypes. Given that these annotations are not (and cannot be) cross-compiled to Scala.js, we can not use them on the shared models. So we need a way to achieve the same without annotations.
Google search reveals that it may be possible do it by directly using the ObjectMapper API. But I am unable to connect it all. Is it possible to add some documentation around this aspect in the next milestone? This is currently blocking us from taking on the full migration.
Almost all our request side models/ADTs are wrapped inside top-level messages. But I also see that some of our response side models/ADTs are not wrapped inside top-level messages.
So as of now, we seem to have both. Will not having a top-level ADTs make the matter simpler?
BTW, my concern with annotations was more general. For example, we may want to use @JsonIgnore to have lazy-vals not get serialized. Can we do that without annotation?
I think it will be difficult if you can’t use annotations. Then you probably would have to write a lot of custom Jackson Serializers/Deserializers, and then it’s questionable if Jackson is a good choice for you.
Jackson has some support for “mix-in” annotations:
This does require configuring the ObjectMapper. @patriknw can correct me if I’m mistaken, but I believe the plan is to have a hook for configuring the ObjectMapper.
val customJacksonObjectMapperFactory = new JacksonObjectMapperFactory {
override def newObjectMapper(bindingName: String, jsonFactory: Option[JsonFactory]): ObjectMapper = {
if (bindingName == "jackson-json") {
val mapper = new ObjectMapper(jsonFactory.orNull)
mapper.addMixIn(targetClass, mixinClass)
mapper
} else
super.newObjectMapper(bindingName, jsonFactory)
}
}
val setup = ActorSystemSetup()
.withSetup(JacksonObjectMapperProviderSetup(customJacksonObjectMapperFactory))
.withSetup(BootstrapSetup(config))
ActorSystem("MySystem", setup)
However, in the documentation you linked to it describes that it’s possible to define mix-ins via a module instead. That might be easier because additional modules can be configured.
@mushtaq If this works for you a contribution to the Akka documentation describing how to use mix-ins would be welcome.
Some additional context: For some of our shared data models, there is already a static cbor-codec defined using the fantastic borer library. We were required to do that so as to publish them in Redis.
We are now thinking, maybe we should add borer codecs for the remaining ones and then implement the Serializer interface to dynamically dispatch to those codecs.