From 840cacfd2a7c26d41842f17db649ebcfdf5335b8 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 21 Dec 2011 11:25:40 +0100 Subject: [PATCH] initial commit on serialization docs --- .../main/scala/akka/testing/Serializers.scala | 75 ------------------- .../akka/serialization/SerializeSpec.scala | 30 ++++++-- akka-actor/src/main/resources/reference.conf | 4 +- .../docs/extension/SerializationDocSpec.scala | 31 ++++++++ akka-docs/scala/serialization.rst | 26 ++++++- .../serialization/ProtobufSerializer.scala | 26 +++++++ 6 files changed, 104 insertions(+), 88 deletions(-) delete mode 100644 akka-actor-tests/src/main/scala/akka/testing/Serializers.scala create mode 100644 akka-docs/scala/code/akka/docs/extension/SerializationDocSpec.scala create mode 100644 akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala diff --git a/akka-actor-tests/src/main/scala/akka/testing/Serializers.scala b/akka-actor-tests/src/main/scala/akka/testing/Serializers.scala deleted file mode 100644 index de7d0924ea..0000000000 --- a/akka-actor-tests/src/main/scala/akka/testing/Serializers.scala +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (C) 2009-2011 Typesafe Inc. - */ - -package akka.testing - -import akka.serialization.Serializer -import com.google.protobuf.Message -import org.codehaus.jackson.map.ObjectMapper -import java.io.{ ObjectOutputStream, ByteArrayOutputStream, ObjectInputStream, ByteArrayInputStream } -import akka.util.ClassLoaderObjectInputStream -import sjson.json._ - -class ProtobufSerializer extends Serializer { - val ARRAY_OF_BYTE_ARRAY = Array[Class[_]](classOf[Array[Byte]]) - - def identifier = 2: Byte - - def toBinary(obj: AnyRef): Array[Byte] = { - if (!obj.isInstanceOf[Message]) throw new IllegalArgumentException( - "Can't serialize a non-protobuf message using protobuf [" + obj + "]") - obj.asInstanceOf[Message].toByteArray - } - - def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]], classLoader: Option[ClassLoader] = None): AnyRef = { - if (!clazz.isDefined) throw new IllegalArgumentException( - "Need a protobuf message class to be able to serialize bytes using protobuf") - clazz.get.getDeclaredMethod("parseFrom", ARRAY_OF_BYTE_ARRAY: _*).invoke(null, bytes).asInstanceOf[Message] - } -} -object ProtobufSerializer extends ProtobufSerializer - -class JavaJSONSerializer extends Serializer { - private val mapper = new ObjectMapper - - def identifier = 3: Byte - - def toBinary(obj: AnyRef): Array[Byte] = { - val bos = new ByteArrayOutputStream - val out = new ObjectOutputStream(bos) - mapper.writeValue(out, obj) - out.close - bos.toByteArray - } - - def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]], classLoader: Option[ClassLoader] = None): AnyRef = { - if (!clazz.isDefined) throw new IllegalArgumentException( - "Can't deserialize JSON to instance if no class is provided") - val in = - if (classLoader.isDefined) new ClassLoaderObjectInputStream(classLoader.get, new ByteArrayInputStream(bytes)) - else new ObjectInputStream(new ByteArrayInputStream(bytes)) - val obj = mapper.readValue(in, clazz.get).asInstanceOf[AnyRef] - in.close - obj - } -} -object JavaJSONSerializer extends JavaJSONSerializer - -class SJSONSerializer extends Serializer { - - def identifier = 4: Byte - - def toBinary(obj: AnyRef): Array[Byte] = - sjson.json.Serializer.SJSON.out(obj) - - def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]], cl: Option[ClassLoader] = None): AnyRef = { - if (!clazz.isDefined) throw new IllegalArgumentException( - "Can't deserialize JSON to instance if no class is provided") - - import sjson.json.Serializer._ - val sj = new SJSON with DefaultConstructor { val classLoader = cl } - sj.in(bytes, clazz.get.getName) - } -} -object SJSONSerializer extends SJSONSerializer diff --git a/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala b/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala index f90f651065..d449510351 100644 --- a/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala @@ -4,8 +4,6 @@ package akka.serialization -import akka.serialization.Serialization._ -import scala.reflect._ import akka.testkit.AkkaSpec import com.typesafe.config.ConfigFactory import akka.actor._ @@ -13,6 +11,26 @@ import java.io._ import akka.dispatch.Await import akka.util.Timeout import akka.util.duration._ +import scala.reflect.BeanInfo +import com.google.protobuf.Message + +class ProtobufSerializer extends Serializer { + val ARRAY_OF_BYTE_ARRAY = Array[Class[_]](classOf[Array[Byte]]) + + def identifier = 2: Byte + + def toBinary(obj: AnyRef): Array[Byte] = { + if (!obj.isInstanceOf[Message]) throw new IllegalArgumentException( + "Can't serialize a non-protobuf message using protobuf [" + obj + "]") + obj.asInstanceOf[Message].toByteArray + } + + def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]], classLoader: Option[ClassLoader] = None): AnyRef = { + if (!clazz.isDefined) throw new IllegalArgumentException( + "Need a protobuf message class to be able to serialize bytes using protobuf") + clazz.get.getDeclaredMethod("parseFrom", ARRAY_OF_BYTE_ARRAY: _*).invoke(null, bytes).asInstanceOf[Message] + } +} object SerializeSpec { @@ -21,14 +39,10 @@ object SerializeSpec { actor { serializers { java = "akka.serialization.JavaSerializer" - proto = "akka.testing.ProtobufSerializer" - sjson = "akka.testing.SJSONSerializer" - default = "akka.serialization.JavaSerializer" } serialization-bindings { - java = ["akka.serialization.SerializeSpec$Address", "akka.serialization.MyJavaSerializableActor", "akka.serialization.MyStatelessActorWithMessagesInMailbox", "akka.serialization.MyActorWithProtobufMessagesInMailbox"] - sjson = ["akka.serialization.SerializeSpec$Person"] + java = ["akka.serialization.SerializeSpec$Person", "akka.serialization.SerializeSpec$Address", "akka.serialization.MyJavaSerializableActor", "akka.serialization.MyStatelessActorWithMessagesInMailbox", "akka.serialization.MyActorWithProtobufMessagesInMailbox"] proto = ["com.google.protobuf.Message", "akka.actor.ProtobufProtocol$MyMessage"] } } @@ -57,7 +71,7 @@ class SerializeSpec extends AkkaSpec(SerializeSpec.serializationConf) { "have correct bindings" in { ser.bindings(addr.getClass.getName) must be("java") - ser.bindings(person.getClass.getName) must be("sjson") + ser.bindings("akka.actor.ProtobufProtocol$MyMessage") must be("proto") } "serialize Address" in { diff --git a/akka-actor/src/main/resources/reference.conf b/akka-actor/src/main/resources/reference.conf index 6dd2b2a452..8e45379592 100644 --- a/akka-actor/src/main/resources/reference.conf +++ b/akka-actor/src/main/resources/reference.conf @@ -197,8 +197,7 @@ akka { # class is not found, then the default serializer (Java serialization) is used. serializers { # java = "akka.serialization.JavaSerializer" - # proto = "akka.testing.ProtobufSerializer" - # sjson = "akka.testing.SJSONSerializer" + # proto = "akka.serialization.ProtobufSerializer" default = "akka.serialization.JavaSerializer" } @@ -208,7 +207,6 @@ akka { # "akka.serialization.MyJavaSerializableActor", # "akka.serialization.MyStatelessActorWithMessagesInMailbox", # "akka.serialization.MyActorWithProtobufMessagesInMailbox"] - # sjson = ["akka.serialization.SerializeSpec$Person"] # proto = ["com.google.protobuf.Message", # "akka.actor.ProtobufProtocol$MyMessage"] # } diff --git a/akka-docs/scala/code/akka/docs/extension/SerializationDocSpec.scala b/akka-docs/scala/code/akka/docs/extension/SerializationDocSpec.scala new file mode 100644 index 0000000000..07c3d7c335 --- /dev/null +++ b/akka-docs/scala/code/akka/docs/extension/SerializationDocSpec.scala @@ -0,0 +1,31 @@ +/** + * Copyright (C) 2009-2011 Typesafe Inc. + */ +package akka.docs.extension + +import org.scalatest.WordSpec +import org.scalatest.matchers.MustMatchers + +class SerializationDocSpec extends WordSpec with MustMatchers { + + "demonstrate how to use Serialization" in { + """ + serializers { + # java = "akka.serialization.JavaSerializer" + # proto = "akka.serialization.ProtobufSerializer" + + default = "akka.serialization.JavaSerializer" + } + + # serialization-bindings { + # java = ["akka.serialization.SerializeSpec$Address", + # "akka.serialization.MyJavaSerializableActor", + # "akka.serialization.MyStatelessActorWithMessagesInMailbox", + # "akka.serialization.MyActorWithProtobufMessagesInMailbox"] + # proto = ["com.google.protobuf.Message", + # "akka.actor.ProtobufProtocol$MyMessage"] + # } + """ + } + +} diff --git a/akka-docs/scala/serialization.rst b/akka-docs/scala/serialization.rst index 0f7dce63b4..b338e66891 100644 --- a/akka-docs/scala/serialization.rst +++ b/akka-docs/scala/serialization.rst @@ -5,8 +5,30 @@ Serialization (Scala) ###################### -Serialization will soon be documented. +.. sidebar:: Contents + + .. contents:: :local: + +Akka has a built-in Extension (TODO ADD REF) for serialization, +and it is both possible to use the built-in serializers and to write your own. + +The serialization mechanism is both used by Akka internally to serialize messages, +and available for ad-hoc serialization of whatever you might need it for. + +Usage +===== + +Configuration +------------- + +Programmatic +------------ + +Customization +============= + +Creating new Serializers +------------------------ -Until then we refer to the following section in the configuration file: * `Serializers `_ \ No newline at end of file diff --git a/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala b/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala new file mode 100644 index 0000000000..ae908bdd48 --- /dev/null +++ b/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2009-2011 Typesafe Inc. + */ + +package akka.serialization + +import akka.serialization.Serializer +import com.google.protobuf.Message + +class ProtobufSerializer extends Serializer { + val ARRAY_OF_BYTE_ARRAY = Array[Class[_]](classOf[Array[Byte]]) + + def identifier = 2: Byte + + def toBinary(obj: AnyRef): Array[Byte] = { + if (!obj.isInstanceOf[Message]) throw new IllegalArgumentException( + "Can't serialize a non-protobuf message using protobuf [" + obj + "]") + obj.asInstanceOf[Message].toByteArray + } + + def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]], classLoader: Option[ClassLoader] = None): AnyRef = { + if (!clazz.isDefined) throw new IllegalArgumentException( + "Need a protobuf message class to be able to serialize bytes using protobuf") + clazz.get.getDeclaredMethod("parseFrom", ARRAY_OF_BYTE_ARRAY: _*).invoke(null, bytes).asInstanceOf[Message] + } +} \ No newline at end of file