Cleanup of serialization docs

This commit is contained in:
Patrik Nordwall 2011-04-29 17:07:52 +02:00
parent 3366dd507c
commit 888af3479e
2 changed files with 93 additions and 81 deletions

View file

@ -1,10 +1,16 @@
.. _serialization-java:
Serialization (Java) Serialization (Java)
==================== ====================
Akka serialization module has been documented extensively under the Scala API section. In this section we will point out the different APIs that are available in Akka for Java based serialization of ActorRefs. The Scala APIs of ActorSerialization has implicit Format objects that set up the type class based serialization. In the Java API, the Format objects need to be specified explicitly. .. sidebar:: Contents
.. contents:: :local:
Akka serialization module has been documented extensively under the :ref:`serialization-scala` section. In this section we will point out the different APIs that are available in Akka for Java based serialization of ActorRefs. The Scala APIs of ActorSerialization has implicit Format objects that set up the type class based serialization. In the Java API, the Format objects need to be specified explicitly.
Serialization of ActorRef Serialization of ActorRef
========================= -------------------------
The following are the Java APIs for serialization of local ActorRefs: The following are the Java APIs for serialization of local ActorRefs:
@ -26,10 +32,9 @@ The following are the Java APIs for serialization of local ActorRefs:
The following steps describe the procedure for serializing an Actor and ActorRef. The following steps describe the procedure for serializing an Actor and ActorRef.
Serialization of a Stateless Actor Serialization of a Stateless Actor
================================== ----------------------------------
Step 1: Define the Actor Step 1: Define the Actor
------------------------
.. code-block:: scala .. code-block:: scala
@ -40,7 +45,6 @@ Step 1: Define the Actor
} }
Step 2: Define the typeclass instance for the actor Step 2: Define the typeclass instance for the actor
---------------------------------------------------
Note how the generated Java classes are accessed using the $class based naming convention of the Scala compiler. Note how the generated Java classes are accessed using the $class based naming convention of the Scala compiler.
@ -58,7 +62,7 @@ Note how the generated Java classes are accessed using the $class based naming c
} }
} }
**Step 3: Serialize and de-serialize** Step 3: Serialize and de-serialize
The following JUnit snippet first creates an actor using the default constructor. The actor is, as we saw above a stateless one. Then it is serialized and de-serialized to get back the original actor. Being stateless, the de-serialized version behaves in the same way on a message as the original actor. The following JUnit snippet first creates an actor using the default constructor. The actor is, as we saw above a stateless one. Then it is serialized and de-serialized to get back the original actor. Being stateless, the de-serialized version behaves in the same way on a message as the original actor.
@ -91,12 +95,11 @@ The following JUnit snippet first creates an actor using the default constructor
} }
Serialization of a Stateful Actor Serialization of a Stateful Actor
================================= ---------------------------------
Let's now have a look at how to serialize an actor that carries a state with it. Here the expectation is that the serialization of the actor will also persist the state information. And after de-serialization we will get back the state with which it was serialized. Let's now have a look at how to serialize an actor that carries a state with it. Here the expectation is that the serialization of the actor will also persist the state information. And after de-serialization we will get back the state with which it was serialized.
Step 1: Define the Actor Step 1: Define the Actor
------------------------
Here we consider an actor defined in Scala. We will however serialize using the Java APIs. Here we consider an actor defined in Scala. We will however serialize using the Java APIs.
@ -119,7 +122,6 @@ Here we consider an actor defined in Scala. We will however serialize using the
Note the actor has a state in the form of an Integer. And every message that the actor receives, it replies with an addition to the integer member. Note the actor has a state in the form of an Integer. And every message that the actor receives, it replies with an addition to the integer member.
Step 2: Define the instance of the typeclass Step 2: Define the instance of the typeclass
--------------------------------------------
.. code-block:: java .. code-block:: java
@ -141,7 +143,6 @@ Step 2: Define the instance of the typeclass
Note the usage of Protocol Buffers to serialize the state of the actor. Note the usage of Protocol Buffers to serialize the state of the actor.
Step 3: Serialize and de-serialize Step 3: Serialize and de-serialize
----------------------------------
.. code-block:: java .. code-block:: java

View file

@ -1,10 +1,16 @@
.. _serialization-scala:
Serialization (Scala) Serialization (Scala)
===================== =====================
.. sidebar:: Contents
.. contents:: :local:
Module stability: **SOLID** Module stability: **SOLID**
Serialization of ActorRef Serialization of ActorRef
========================= -------------------------
An Actor can be serialized in two different ways: An Actor can be serialized in two different ways:
@ -13,7 +19,7 @@ An Actor can be serialized in two different ways:
Both of these can be sent as messages over the network and/or store them to disk, in a persistent storage backend etc. Both of these can be sent as messages over the network and/or store them to disk, in a persistent storage backend etc.
Actor serialization in Akka is implemented through a type class 'Format[T <: Actor]' which publishes the 'fromBinary' and 'toBinary' methods for serialization. Here's the complete definition of the type class: Actor serialization in Akka is implemented through a type class ``Format[T <: Actor]`` which publishes the ``fromBinary`` and ``toBinary`` methods for serialization. Here's the complete definition of the type class:
.. code-block:: scala .. code-block:: scala
@ -31,15 +37,14 @@ Actor serialization in Akka is implemented through a type class 'Format[T <: Act
// client needs to implement Format[] for the respective actor // client needs to implement Format[] for the respective actor
trait Format[T <: Actor] extends FromBinary[T] with ToBinary[T] trait Format[T <: Actor] extends FromBinary[T] with ToBinary[T]
**Deep serialization of an Actor and ActorRef** Deep serialization of an Actor and ActorRef
----------------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can serialize the whole actor deeply, e.g. both the 'ActorRef' and then instance of its 'Actor'. This can be useful if you want to move an actor from one node to another, or if you want to store away an actor, with its state, into a database. You can serialize the whole actor deeply, e.g. both the ``ActorRef`` and then instance of its ``Actor``. This can be useful if you want to move an actor from one node to another, or if you want to store away an actor, with its state, into a database.
Here is an example of how to serialize an Actor. Here is an example of how to serialize an Actor.
Step 1: Define the actor Step 1: Define the actor
^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: scala .. code-block:: scala
@ -54,7 +59,6 @@ Step 1: Define the actor
} }
Step 2: Implement the type class for the actor Step 2: Implement the type class for the actor
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: scala .. code-block:: scala
@ -72,7 +76,6 @@ Step 2: Implement the type class for the actor
} }
Step 3: Import the type class module definition and serialize / de-serialize Step 3: Import the type class module definition and serialize / de-serialize
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: scala .. code-block:: scala
@ -90,7 +93,8 @@ Step 3: Import the type class module definition and serialize / de-serialize
(actor2 !! "hello").getOrElse("_") should equal("world 3") (actor2 !! "hello").getOrElse("_") should equal("world 3")
} }
**Helper Type Class for Stateless Actors** Helper Type Class for Stateless Actors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If your actor is stateless, then you can use the helper trait that Akka provides to serialize / de-serialize. Here's the definition: If your actor is stateless, then you can use the helper trait that Akka provides to serialize / de-serialize. Here's the definition:
@ -138,9 +142,10 @@ and use it for serialization:
(actor2 !! "hello").getOrElse("_") should equal("world") (actor2 !! "hello").getOrElse("_") should equal("world")
} }
**Helper Type Class for actors with external serializer** Helper Type Class for actors with external serializer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use the trait 'SerializerBasedActorFormat' for specifying serializers. Use the trait ``SerializerBasedActorFormat`` for specifying serializers.
.. code-block:: scala .. code-block:: scala
@ -192,14 +197,14 @@ and serialize / de-serialize ..
(actor2 !! "hello").getOrElse("_") should equal("world 3") (actor2 !! "hello").getOrElse("_") should equal("world 3")
} }
**Serialization of a RemoteActorRef** Serialization of a RemoteActorRef
------------------------------------- ---------------------------------
You can serialize an 'ActorRef' to an immutable, network-aware Actor reference that can be freely shared across the network, a reference that "remembers" and stay mapped to its original Actor instance and host node, and will always work as expected. You can serialize an ``ActorRef`` to an immutable, network-aware Actor reference that can be freely shared across the network, a reference that "remembers" and stay mapped to its original Actor instance and host node, and will always work as expected.
The 'RemoteActorRef' serialization is based upon Protobuf (Google Protocol Buffers) and you don't need to do anything to use it, it works on any 'ActorRef' (as long as the actor has **not** implemented one of the 'SerializableActor' traits, since then deep serialization will happen). The ``RemoteActorRef`` serialization is based upon Protobuf (Google Protocol Buffers) and you don't need to do anything to use it, it works on any ``ActorRef`` (as long as the actor has **not** implemented one of the ``SerializableActor`` traits, since then deep serialization will happen).
Currently Akka will **not** autodetect an 'ActorRef' as part of your message and serialize it for you automatically, so you have to do that manually or as part of your custom serialization mechanisms. Currently Akka will **not** autodetect an ``ActorRef`` as part of your message and serialize it for you automatically, so you have to do that manually or as part of your custom serialization mechanisms.
Here is an example of how to serialize an Actor. Here is an example of how to serialize an Actor.
@ -209,14 +214,14 @@ Here is an example of how to serialize an Actor.
val bytes = toBinary(actor1) val bytes = toBinary(actor1)
To deserialize the 'ActorRef' to a 'RemoteActorRef' you need to use the 'fromBinaryToRemoteActorRef(bytes: Array[Byte])' method on the 'ActorRef' companion object: To deserialize the ``ActorRef`` to a ``RemoteActorRef`` you need to use the ``fromBinaryToRemoteActorRef(bytes: Array[Byte])`` method on the ``ActorRef`` companion object:
.. code-block:: scala .. code-block:: scala
import RemoteActorSerialization._ import RemoteActorSerialization._
val actor2 = fromBinaryToRemoteActorRef(bytes) val actor2 = fromBinaryToRemoteActorRef(bytes)
You can also pass in a class loader to load the 'ActorRef' class and dependencies from: You can also pass in a class loader to load the ``ActorRef`` class and dependencies from:
.. code-block:: scala .. code-block:: scala
@ -226,14 +231,12 @@ You can also pass in a class loader to load the 'ActorRef' class and dependencie
Deep serialization of a TypedActor Deep serialization of a TypedActor
---------------------------------- ----------------------------------
Serialization of typed actors works almost the same way as untyped actors. You can serialize the whole actor deeply, e.g. both the 'proxied ActorRef' and the instance of its 'TypedActor'. Serialization of typed actors works almost the same way as untyped actors. You can serialize the whole actor deeply, e.g. both the 'proxied ActorRef' and the instance of its ``TypedActor``.
Here is the example from above implemented as a TypedActor. Here is the example from above implemented as a TypedActor.
^
Step 1: Define the actor Step 1: Define the actor
^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: scala .. code-block:: scala
@ -252,7 +255,6 @@ Step 1: Define the actor
} }
Step 2: Implement the type class for the actor Step 2: Implement the type class for the actor
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: scala .. code-block:: scala
@ -266,7 +268,6 @@ Step 2: Implement the type class for the actor
} }
Step 3: Import the type class module definition and serialize / de-serialize Step 3: Import the type class module definition and serialize / de-serialize
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: scala .. code-block:: scala
@ -278,12 +279,12 @@ Step 3: Import the type class module definition and serialize / de-serialize
val typedActor2: MyTypedActor = fromBinaryJ(bytes, f) //type hint needed val typedActor2: MyTypedActor = fromBinaryJ(bytes, f) //type hint needed
typedActor2.requestReply("hello") typedActor2.requestReply("hello")
-
Serialization of a remote typed ActorRef Serialization of a remote typed ActorRef
---------------------------------------- ----------------------------------------
To deserialize the TypedActor to a 'RemoteTypedActorRef' (an aspectwerkz proxy to a RemoteActorRef) you need to use the 'fromBinaryToRemoteTypedActorRef(bytes: Array[Byte])' method on 'RemoteTypedActorSerialization' object: To deserialize the TypedActor to a ``RemoteTypedActorRef`` (an aspectwerkz proxy to a RemoteActorRef) you need to use the ``fromBinaryToRemoteTypedActorRef(bytes: Array[Byte])`` method on ``RemoteTypedActorSerialization`` object:
.. code-block:: scala .. code-block:: scala
@ -294,7 +295,7 @@ To deserialize the TypedActor to a 'RemoteTypedActorRef' (an aspectwerkz proxy t
val typedActor2 = fromBinaryToRemoteTypedActorRef(bytes, classLoader) val typedActor2 = fromBinaryToRemoteTypedActorRef(bytes, classLoader)
Compression Compression
=========== -----------
Akka has a helper class for doing compression of binary data. This can be useful for example when storing data in one of the backing storages. It currently supports LZF which is a very fast compression algorithm suited for runtime dynamic compression. Akka has a helper class for doing compression of binary data. This can be useful for example when storing data in one of the backing storages. It currently supports LZF which is a very fast compression algorithm suited for runtime dynamic compression.
@ -309,24 +310,28 @@ Here is an example of how it can be used:
val uncompressBytes = Compression.LZF.uncompress(compressBytes) val uncompressBytes = Compression.LZF.uncompress(compressBytes)
Using the Serializable trait and Serializer class for custom serialization Using the Serializable trait and Serializer class for custom serialization
========================================================================== --------------------------------------------------------------------------
If you are sending messages to a remote Actor and these messages implement one of the predefined interfaces/traits in the 'akka.serialization.Serializable.*' object, then Akka will transparently detect which serialization format it should use as wire protocol and will automatically serialize and deserialize the message according to this protocol. If you are sending messages to a remote Actor and these messages implement one of the predefined interfaces/traits in the ``akka.serialization.Serializable.*`` object, then Akka will transparently detect which serialization format it should use as wire protocol and will automatically serialize and deserialize the message according to this protocol.
Each serialization interface/trait in Each serialization interface/trait in
* akka.serialization.Serializable.*
> has a matching serializer in - akka.serialization.Serializable.*
* akka.serialization.Serializer.*
has a matching serializer in
- akka.serialization.Serializer.*
Note however that if you are using one of the Serializable interfaces then you dont have to do anything else in regard to sending remote messages. Note however that if you are using one of the Serializable interfaces then you dont have to do anything else in regard to sending remote messages.
The ones currently supported are (besides the default which is regular Java serialization): The ones currently supported are (besides the default which is regular Java serialization):
* ScalaJSON (Scala only)
* JavaJSON (Java but some Scala structures)
* SBinary (Scala only)
* Protobuf (Scala and Java)
Apart from the above, Akka also supports Scala object serialization through `SJSON <http://github.com/debasishg/sjson/tree/master>`_ that implements APIs similar to 'akka.serialization.Serializer.*'. See the section on SJSON below for details. - ScalaJSON (Scala only)
- JavaJSON (Java but some Scala structures)
- SBinary (Scala only)
- Protobuf (Scala and Java)
Apart from the above, Akka also supports Scala object serialization through `SJSON <http://github.com/debasishg/sjson/tree/master>`_ that implements APIs similar to ``akka.serialization.Serializer.*``. See the section on SJSON below for details.
Protobuf Protobuf
-------- --------
@ -482,7 +487,7 @@ You may also see this exception when trying to serialize a case class with out a
@BeanInfo case class Empty() // cannot be serialized @BeanInfo case class Empty() // cannot be serialized
SJSON: Scala SJSON: Scala
------------- ------------
SJSON supports serialization of Scala objects into JSON. It implements support for built in Scala structures like List, Map or String as well as custom objects. SJSON is available as an Apache 2 licensed project on Github `here <http://github.com/debasishg/sjson/tree/master>`_. SJSON supports serialization of Scala objects into JSON. It implements support for built in Scala structures like List, Map or String as well as custom objects. SJSON is available as an Apache 2 licensed project on Github `here <http://github.com/debasishg/sjson/tree/master>`_.
@ -593,7 +598,7 @@ With SJSON, I can do the following:
"Market Street" should equal( "Market Street" should equal(
(r ># { ('addresses ? obj) andThen ('residence ? obj) andThen ('street ? str) })) (r ># { ('addresses ? obj) andThen ('residence ? obj) andThen ('street ? str) }))
^
Changing property names during serialization Changing property names during serialization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -619,7 +624,7 @@ When this will be serialized out, the property name will be changed.
JsString("ISBN") -> JsString("012-456372") JsString("ISBN") -> JsString("012-456372")
) )
^
Serialization with ignore properties Serialization with ignore properties
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -653,7 +658,7 @@ The annotation @JSONProperty can be used to selectively ignore fields. When I se
Similarly, we can ignore properties of an object **only** if they are null and not ignore otherwise. Just specify the annotation @JSONProperty as @JSONProperty {val ignoreIfNull = true}. Similarly, we can ignore properties of an object **only** if they are null and not ignore otherwise. Just specify the annotation @JSONProperty as @JSONProperty {val ignoreIfNull = true}.
^
Serialization with Type Hints for Generic Data Members Serialization with Type Hints for Generic Data Members
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -892,7 +897,8 @@ and the serialization in action in the REPL:
There are other nifty ways to implement case class serialization using sjson. For more details, have a look at the `wiki <http://wiki.github.com/debasishg/sjson/typeclass-based-json-serialization>`_ for sjson. There are other nifty ways to implement case class serialization using sjson. For more details, have a look at the `wiki <http://wiki.github.com/debasishg/sjson/typeclass-based-json-serialization>`_ for sjson.
**<span class="caps" style="line-height: 1.4em; margin: 0px; padding: 0px;">JSON</span>: Java** JSON: Java
----------
Use the akka.serialization.Serialization.JavaJSON base class with its toJSONmethod. Akkas Java JSON is based upon the Jackson library. Use the akka.serialization.Serialization.JavaJSON base class with its toJSONmethod. Akkas Java JSON is based upon the Jackson library.
@ -924,7 +930,6 @@ Use the akka.serialization.SerializerFactory.getJavaJSON to do generic JSON seri
String json = factory.getJavaJSON().out(foo); String json = factory.getJavaJSON().out(foo);
Foo fooCopy = factory.getJavaJSON().in(json, Foo.class); Foo fooCopy = factory.getJavaJSON().in(json, Foo.class);
-
SBinary: Scala SBinary: Scala
-------------- --------------
@ -942,16 +947,22 @@ Here is an example of using the akka.serialization.Serializer.SBinary serializer
val usersCopy = Serializer.SBinary.in(bytes, Some(classOf[List[Tuple2[String,String]]])) val usersCopy = Serializer.SBinary.in(bytes, Some(classOf[List[Tuple2[String,String]]]))
If you need to serialize your own user-defined objects then you have to do three things: If you need to serialize your own user-defined objects then you have to do three things:
# Define an empty constructor
# Mix in the Serializable.SBinary[T] trait, and implement its methods: - Define an empty constructor
## fromBytes(bytes: Array[Byte])[T] - Mix in the Serializable.SBinary[T] trait, and implement its methods:
## toBytes: Array[Byte]
# Create an implicit sbinary.Format[T] object for your class. Which means that you have to define its two methods: - fromBytes(bytes: Array[Byte])[T]
## reads(in: Input): T; in which you read in all the fields in your object, using read[FieldType](in)and recreate it. - toBytes: Array[Byte]
## writes(out: Output, value: T): Unit; in which you write out all the fields in your object, using write[FieldType](out, value.field).
- Create an implicit sbinary.Format[T] object for your class. Which means that you have to define its two methods:
- reads(in: Input): T; in which you read in all the fields in your object, using read[FieldType](in)and recreate it.
- writes(out: Output, value: T): Unit; in which you write out all the fields in your object, using write[FieldType](out, value.field).
Here is an example: Here is an example:
`<code format="scala">`_
.. code-block:: scala
case class User(val usernamePassword: Tuple2[String, String], val email: String, val age: Int) case class User(val usernamePassword: Tuple2[String, String], val email: String, val age: Int)
extends Serializable.SBinary[User] { extends Serializable.SBinary[User] {
import sbinary.DefaultProtocol._ import sbinary.DefaultProtocol._
@ -975,4 +986,4 @@ case class User(val usernamePassword: Tuple2[String, String], val email: String,
def toBytes: Array[Byte] = toByteArray(this) def toBytes: Array[Byte] = toByteArray(this)
} }
`<code>`_