In my previous blogs on Lagom, we discussed Persistent Entity and Read-side and Write side in Lagom. In this blog, I’m going to discuss how serialization is handled in Lagom. But before that let’s understand what serialization is ?
Serialization is a process of converting an object into the stream of bytes so that you can store or transmit it in memory, database etc. Its main purpose is to save the state of the object so that it can be recreated whenever needed.
Serialization in Lagom
Lagom uses Akka serialization mechanisms to bind serializers for each of the message sent over the wire. Preferably we use JSON. We can easily add Play-JSON serialization that is much more familiar to developers.
Why Serialization?
- Persisting events and exchanging messages between the nodes of the cluster requires serialization.
- Request and response messages uses serialization.
- Without serialization it is not possible to deserialize old objects.
Serialization using Play-JSON
To enable JSON serialization you need to follow given steps:
- define your Format for each class that needs serialization
implicit val format: Format[ProductAdded] = Json.format
It is the best practice to define the Format as an implicit in the classes companion object, so that it can be found by implicit resolution.
- implement JsonSerializerRegistry
object UserSerializerRegistry extends JsonSerializerRegistry {
override def serializers: immutable.Seq[JsonSerializer[_]] = immutable.Seq(
JsonSerializer[Product],
JsonSerializer[AddProductCommand],
JsonSerializer[GetProductCommand],
JsonSerializer[ProductAdded],
JsonSerializer[InventoryState]
)
}
- provide the serializer registry by overriding the jsonSerializerRegistry component method in your Application Loader
abstract class LagomPersistentEntityApplication(context: LagomApplicationContext)
extends LagomApplication(context)
with CassandraPersistenceComponents
with AhcWSComponents {
override lazy val jsonSerializerRegistry: JsonSerializerRegistry = UserSerializerRegistry
}
Compression
Sometimes, for large messages it can be beneficial to enable compression. That is done by using the JsonSerializer.compressed[T]
builder method instead of the JsonSerializer.apply[T]
. Compression reduces the size of messages. By default, it compresses the messages that are more than 32Kb.
Defining Format
There are 2 ways for that:
- Automated mapping
The Json.format[MyClass] macro will inspect a case class
for what fields it contains and produce a Format
that uses the field names and types of the class in the resulting JSON. As we don’t have to apply each and every step individually, it is automated mapping.
implicit val format: Format[AddProductCommand] = Json.format[AddProductCommand]
- Manual Mapping
In manual mapping we can use JSON combinators. In JSON combinators we don’t have to write Reads and Writes for producing a Format rather we can just use some functions. Other than cominators we can use reads and writes also. JSON combinators are useful when there is symmetry in Reads and Writes.
Limitation of Serialization in Akka-typed
In Akka Typed, messages often include a replyTo:ActorRef[T] field so the actor handling the message can send a message back. For handling the serialization of the ActorRef[T] it is compulsory to use the Akka Jackson Serializer. You will have to use Akka Jackson to serialize your commands.
You can check for the demo code here.
That’s all about Serialization in Lagom. I hope that was helpful!
References