Merge pull request #17601 from akka/wip-17576-manifest-patriknw

+act #17576 Support serializer with string manifest
This commit is contained in:
Patrik Nordwall 2015-06-01 13:46:17 +02:00
commit 1dac401099
21 changed files with 605 additions and 93 deletions

View file

@ -15,12 +15,13 @@ package docs.serialization {
import akka.actor.ExtendedActorSystem
import akka.actor.Extension
import akka.actor.Address
import java.nio.charset.StandardCharsets
//#my-own-serializer
class MyOwnSerializer extends Serializer {
// This is whether "fromBinary" requires a "clazz" or not
def includeManifest: Boolean = false
def includeManifest: Boolean = true
// Pick a unique identifier for your Serializer,
// you've got a couple of billions to choose from,
@ -37,7 +38,6 @@ package docs.serialization {
// "fromBinary" deserializes the given array,
// using the type hint (if any, see "includeManifest" above)
// into the optionally provided classLoader.
def fromBinary(bytes: Array[Byte],
clazz: Option[Class[_]]): AnyRef = {
// Put your code that deserializes here
@ -48,8 +48,52 @@ package docs.serialization {
}
//#my-own-serializer
//#my-own-serializer2
class MyOwnSerializer2 extends SerializerWithStringManifest {
val CustomerManifest = "customer"
val UserManifest = "user"
val UTF_8 = StandardCharsets.UTF_8.name()
// Pick a unique identifier for your Serializer,
// you've got a couple of billions to choose from,
// 0 - 16 is reserved by Akka itself
def identifier = 1234567
// The manifest (type hint) that will be provided in the fromBinary method
// Use `""` if manifest is not needed.
def manifest(obj: AnyRef): String =
obj match {
case _: Customer => CustomerManifest
case _: User => UserManifest
}
// "toBinary" serializes the given object to an Array of Bytes
def toBinary(obj: AnyRef): Array[Byte] = {
// Put the real code that serializes the object here
obj match {
case Customer(name) => name.getBytes(UTF_8)
case User(name) => name.getBytes(UTF_8)
}
}
// "fromBinary" deserializes the given array,
// using the type hint
def fromBinary(bytes: Array[Byte], manifest: String): AnyRef = {
// Put the real code that deserializes here
manifest match {
case CustomerManifest =>
Customer(new String(bytes, UTF_8))
case UserManifest =>
User(new String(bytes, UTF_8))
}
}
}
//#my-own-serializer2
trait MyOwnSerializable
final case class Customer(name: String) extends MyOwnSerializable
final case class User(name: String) extends MyOwnSerializable
class SerializationDocSpec extends AkkaSpec {
"demonstrate configuration of serialize messages" in {

View file

@ -95,9 +95,38 @@ First you need to create a class definition of your ``Serializer`` like so:
:include: imports,my-own-serializer
:exclude: ...
The manifest is a type hint so that the same serializer can be used for different
classes. The manifest parameter in ``fromBinary`` is the class of the object that
was serialized. In ``fromBinary`` you can match on the class and deserialize the
bytes to different objects.
Then you only need to fill in the blanks, bind it to a name in your :ref:`configuration` and then
list which classes that should be serialized using it.
Serializer with String Manifest
-------------------------------
The ``Serializer`` illustrated above supports a class based manifest (type hint).
For serialization of data that need to evolve over time the `SerializerWithStringManifest`
is recommended instead of ``Serializer`` because the manifest (type hint) is a ``String``
instead of a ``Class``. That means that the class can be moved/removed and the serializer
can still deserialize old data by matching on the ``String``. This is especially useful
for :ref:`persistence-scala`.
The manifest string can also encode a version number that can be used in ``fromBinary`` to
deserialize in different ways to migrate old data to new domain objects.
If the data was originally serialized with ``Serializer`` and in a later version of the
system you change to ``SerializerWithStringManifest`` the manifest string will be the full
class name if you used ``includeManifest=true``, otherwise it will be the empty string.
This is how a ``SerializerWithStringManifest`` looks like:
.. includecode:: code/docs/serialization/SerializationDocSpec.scala#my-own-serializer2
You must also bind it to a name in your :ref:`configuration` and then list which classes
that should be serialized using it.
Serializing ActorRefs
---------------------