Merge branch 'master' of github.com:jboner/akka

This commit is contained in:
David Greco 2010-09-23 19:37:43 +02:00
commit 11b5732b0c
7 changed files with 220 additions and 58 deletions

View file

@ -28,17 +28,21 @@ object MessageSerializer extends Logging {
messageProtocol.getSerializationScheme match {
case SerializationSchemeType.JAVA =>
unbox(SERIALIZER_JAVA.fromBinary(messageProtocol.getMessage.toByteArray, None))
case SerializationSchemeType.PROTOBUF =>
val clazz = loadManifest(SERIALIZER_PROTOBUF.classLoader, messageProtocol)
SERIALIZER_PROTOBUF.fromBinary(messageProtocol.getMessage.toByteArray, Some(clazz))
case SerializationSchemeType.SBINARY =>
val clazz = loadManifest(SERIALIZER_SBINARY.classLoader, messageProtocol)
val renderer = clazz.newInstance.asInstanceOf[Serializable.SBinary[_ <: AnyRef]]
renderer.fromBytes(messageProtocol.getMessage.toByteArray)
case SerializationSchemeType.SCALA_JSON =>
val clazz = loadManifest(SERIALIZER_SCALA_JSON.classLoader, messageProtocol)
import scala.reflect._
SERIALIZER_SCALA_JSON.fromBinary(messageProtocol.getMessage.toByteArray)(Manifest.classType(clazz))
val renderer = clazz.newInstance.asInstanceOf[Serializable.ScalaJSON[_]]
renderer.fromBytes(messageProtocol.getMessage.toByteArray)
case SerializationSchemeType.JAVA_JSON =>
val clazz = loadManifest(SERIALIZER_JAVA_JSON.classLoader, messageProtocol)
SERIALIZER_JAVA_JSON.fromBinary(messageProtocol.getMessage.toByteArray, Some(clazz))
@ -52,9 +56,9 @@ object MessageSerializer extends Logging {
builder.setSerializationScheme(SerializationSchemeType.PROTOBUF)
builder.setMessage(ByteString.copyFrom(serializable.toByteArray))
builder.setMessageManifest(ByteString.copyFromUtf8(serializable.getClass.getName))
} else if (message.isInstanceOf[Serializable.ScalaJSON]) {
} else if (message.isInstanceOf[Serializable.ScalaJSON[_]]) {
builder.setSerializationScheme(SerializationSchemeType.SCALA_JSON)
setMessageAndManifest(builder, message.asInstanceOf[Serializable.ScalaJSON])
setMessageAndManifest(builder, message.asInstanceOf[Serializable.ScalaJSON[_ <: Any]])
} else if (message.isInstanceOf[Serializable.SBinary[_]]) {
builder.setSerializationScheme(SerializationSchemeType.SBINARY)
setMessageAndManifest(builder, message.asInstanceOf[Serializable.SBinary[_ <: Any]])

View file

@ -91,10 +91,32 @@ object Serializable {
}
/**
* case class Address(street: String, city: String, zip: String)
* extends ScalaJSON[Address] {
*
* implicit val AddressFormat: Format[Address] =
* asProduct3("street", "city", "zip")(Address)(Address.unapply(_).get)
*
* import dispatch.json._
* import sjson.json._
* import sjson.json.JsonSerialization._
*
* def toJSON: String = JsValue.toJson(tojson(this))
* def toBytes: Array[Byte] = tobinary(this)
* def fromBytes(bytes: Array[Byte]): Address = frombinary[Address](bytes)
* def fromJSON(js: String): Address = fromjson[Address](Js(js))
* }
*
* val a = Address(...)
* val js = tojson(a)
* val add = fromjson[Address](js)
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
trait ScalaJSON extends JSON {
trait ScalaJSON[T] extends JSON {
def toJSON: String = new String(toBytes, "UTF-8")
def toBytes: Array[Byte] = SJSONSerializer.SJSON.out(this)
def fromJSON(js: String): T
def toBytes: Array[Byte]
def fromBytes(bytes: Array[Byte]): T
}
}

View file

@ -128,11 +128,24 @@ object Serializer {
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object ScalaJSON extends ScalaJSON
trait ScalaJSON extends Serializer {
trait ScalaJSON {
import dispatch.json._
import sjson.json._
var classLoader: Option[ClassLoader] = None
def tojson[T](o: T)(implicit tjs: Writes[T]): JsValue = JsonSerialization.tojson(o)(tjs)
def fromjson[T](json: JsValue)(implicit fjs: Reads[T]): T = JsonSerialization.fromjson(json)(fjs)
def tobinary[T](o: T)(implicit tjs: Writes[T]): Array[Byte] = JsonSerialization.tobinary(o)(tjs)
def frombinary[T](bytes: Array[Byte])(implicit fjs: Reads[T]): T = JsonSerialization.frombinary(bytes)(fjs)
// backward compatibility
// implemented using refelction based json serialization
def toBinary(obj: AnyRef): Array[Byte] = SJSONSerializer.SJSON.out(obj)
// FIXME set ClassLoader on SJSONSerializer.SJSON
def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef = SJSONSerializer.SJSON.in(bytes)
import scala.reflect.Manifest
@ -144,6 +157,7 @@ object Serializer {
SJSONSerializer.SJSON.in(bytes)(m)
}
}
object ScalaJSON extends ScalaJSON
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>

View file

@ -0,0 +1,67 @@
package se.scalablesolutions.akka.serialization
import org.scalatest.Spec
import org.scalatest.matchers.ShouldMatchers
import org.scalatest.BeforeAndAfterAll
import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith
import se.scalablesolutions.akka.serialization.Serializable.ScalaJSON
object Serializables {
import sjson.json.DefaultProtocol._
case class Shop(store: String, item: String, price: Int) extends
ScalaJSON[Shop] {
implicit val ShopFormat: sjson.json.Format[Shop] =
asProduct3("store", "item", "price")(Shop)(Shop.unapply(_).get)
import dispatch.json._
import sjson.json._
import sjson.json.JsonSerialization._
def toBytes: Array[Byte] = tobinary(this)
def fromBytes(bytes: Array[Byte]) = frombinary[Shop](bytes)
def fromJSON(js: String) = fromjson[Shop](Js(js))
}
case class MyMessage(val id: String, val value: Tuple2[String, Int])
implicit val MyMessageFormat: sjson.json.Format[MyMessage] =
asProduct2("id", "value")(MyMessage)(MyMessage.unapply(_).get)
case class MyJsonObject(val key: String, val map: Map[String, Int],
val standAloneInt: Int) extends ScalaJSON[MyJsonObject] {
implicit val MyJsonObjectFormat: sjson.json.Format[MyJsonObject] =
asProduct3("key", "map", "standAloneInt")(MyJsonObject)(MyJsonObject.unapply(_).get)
import dispatch.json._
import sjson.json._
import sjson.json.JsonSerialization._
def toBytes: Array[Byte] = tobinary(this)
def fromBytes(bytes: Array[Byte]) = frombinary[MyJsonObject](bytes)
def fromJSON(js: String) = fromjson[MyJsonObject](Js(js))
}
}
@RunWith(classOf[JUnitRunner])
class ScalaJSONSerializableSpec extends
Spec with
ShouldMatchers with
BeforeAndAfterAll {
import Serializables._
describe("Serialization of case classes") {
it("should be able to serialize and de-serialize") {
val s = Shop("Target", "cooker", 120)
s.fromBytes(s.toBytes) should equal(s)
s.fromJSON(s.toJSON) should equal(s)
val key: String = "myKey"
val value: Int = 123
val standAloneInt: Int = 35
val message = MyJsonObject(key, Map(key -> value), standAloneInt)
message.fromBytes(message.toBytes) should equal(message)
message.fromJSON(message.toJSON) should equal(message)
}
}
}

View file

@ -0,0 +1,52 @@
package se.scalablesolutions.akka.serialization
import org.scalatest.Spec
import org.scalatest.matchers.ShouldMatchers
import org.scalatest.BeforeAndAfterAll
import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith
import se.scalablesolutions.akka.serialization.Serializer.ScalaJSON
object Protocols {
import sjson.json.DefaultProtocol._
case class Shop(store: String, item: String, price: Int)
implicit val ShopFormat: sjson.json.Format[Shop] =
asProduct3("store", "item", "price")(Shop)(Shop.unapply(_).get)
case class MyMessage(val id: String, val value: Tuple2[String, Int])
implicit val MyMessageFormat: sjson.json.Format[MyMessage] =
asProduct2("id", "value")(MyMessage)(MyMessage.unapply(_).get)
case class MyJsonObject(val key: String, val map: Map[String, Int],
val standAloneInt: Int)
implicit val MyJsonObjectFormat: sjson.json.Format[MyJsonObject] =
asProduct3("key", "map", "standAloneInt")(MyJsonObject)(MyJsonObject.unapply(_).get)
}
@RunWith(classOf[JUnitRunner])
class ScalaJSONSerializerSpec extends
Spec with
ShouldMatchers with
BeforeAndAfterAll {
import Protocols._
import ScalaJSON._
describe("Serialization of case classes") {
it("should be able to serialize and de-serialize") {
val s = Shop("Target", "cooker", 120)
fromjson[Shop](tojson(s)) should equal(s)
frombinary[Shop](tobinary(s)) should equal(s)
val o = MyMessage("dg", ("akka", 100))
fromjson[MyMessage](tojson(o)) should equal(o)
frombinary[MyMessage](tobinary(o)) should equal(o)
val key: String = "myKey"
val value: Int = 123
val standAloneInt: Int = 35
val message = MyJsonObject(key, Map(key -> value), standAloneInt)
fromjson[MyJsonObject](tojson(message)) should equal(message)
}
}
}

View file

@ -8,6 +8,7 @@ import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith
import se.scalablesolutions.akka.serialization._
import dispatch.json._
import se.scalablesolutions.akka.actor._
import ActorSerialization._
import Actor._
@ -52,6 +53,10 @@ class SerializableTypeClassActorSpec extends
implicit object MyStatelessActorFormat extends StatelessActorFormat[MyStatelessActorWithMessagesInMailbox]
}
object BinaryFormatMyActorWithSerializableMessages {
implicit object MyActorWithSerializableMessagesFormat extends StatelessActorFormat[MyActorWithSerializableMessages]
}
object BinaryFormatMyJavaSerializableActor {
implicit object MyJavaSerializableActorFormat extends SerializerBasedActorFormat[MyJavaSerializableActor] {
val serializer = Serializer.Java
@ -139,6 +144,29 @@ class SerializableTypeClassActorSpec extends
(actor3 !! "hello-reply").getOrElse("_") should equal("world")
}
}
describe("Custom serializable actors") {
it("should serialize and de-serialize") {
import BinaryFormatMyActorWithSerializableMessages._
val actor1 = actorOf[MyActorWithSerializableMessages].start
(actor1 ! MyMessage("hello1", ("akka", 100)))
(actor1 ! MyMessage("hello2", ("akka", 200)))
(actor1 ! MyMessage("hello3", ("akka", 300)))
(actor1 ! MyMessage("hello4", ("akka", 400)))
(actor1 ! MyMessage("hello5", ("akka", 500)))
actor1.mailboxSize should be > (0)
val actor2 = fromBinary(toBinary(actor1))
Thread.sleep(1000)
actor2.mailboxSize should be > (0)
(actor2 !! "hello-reply").getOrElse("_") should equal("world")
val actor3 = fromBinary(toBinary(actor1, false))
Thread.sleep(1000)
actor3.mailboxSize should equal(0)
(actor3 !! "hello-reply").getOrElse("_") should equal("world")
}
}
}
class MyActorWithDualCounter extends Actor {
@ -188,3 +216,27 @@ class MyStatelessActorWithMessagesInMailbox extends Actor {
self.reply("world " + count)
}
}
class MyActorWithSerializableMessages extends Actor {
def receive = {
case MyMessage(s, t) =>
println("# messages in mailbox " + self.mailboxSize)
Thread.sleep(500)
case "hello-reply" => self.reply("world")
}
}
case class MyMessage(val id: String, val value: Tuple2[String, Int])
extends Serializable.ScalaJSON[MyMessage] {
def this() = this(null, null)
import sjson.json.DefaultProtocol._
import sjson.json._
import sjson.json.JsonSerialization._
implicit val MyMessageFormat: sjson.json.Format[MyMessage] =
asProduct2("id", "value")(MyMessage)(MyMessage.unapply(_).get)
def toBytes: Array[Byte] = tobinary(this)
def fromBytes(bytes: Array[Byte]) = frombinary[MyMessage](bytes)
def fromJSON(js: String) = fromjson[MyMessage](Js(js))
}

View file

@ -1,49 +0,0 @@
package se.scalablesolutions.akka.actor.serialization
import org.scalatest.Spec
import org.scalatest.matchers.ShouldMatchers
import org.scalatest.BeforeAndAfterAll
import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith
import se.scalablesolutions.akka.serialization.Serializer
import se.scalablesolutions.akka.serialization.Serializable.ScalaJSON
import scala.reflect._
import scala.annotation.target._
import sjson.json.JSONTypeHint
@BeanInfo class MyJsonObject(val key: String,
@(JSONTypeHint @field)(value = classOf[Int])
val map: Map[String, Int],
val standAloneInt: Int) extends ScalaJSON {
private def this() = this(null, null, -1)
override def toString(): String = try {
val mapValue: Int = map.getOrElse(key, -1)
println("Map value: %s".format(mapValue.asInstanceOf[AnyRef].getClass))
"Key: %s, Map value: %d, Stand Alone Int: %d".format(key, mapValue, standAloneInt)
} catch {
case e: ClassCastException => e.getMessage
case _ => "Unknown error"
}
}
@RunWith(classOf[JUnitRunner])
class Ticket436Spec extends
Spec with
ShouldMatchers with
BeforeAndAfterAll {
describe("Serialization of Maps containing Int") {
it("should be able to serialize and de-serialize preserving the data types of the Map") {
val key: String = "myKey"
val value: Int = 123
val standAloneInt: Int = 35
val message = new MyJsonObject(key, Map(key -> value), standAloneInt)
val json = message.toJSON
val copy = Serializer.ScalaJSON.fromJSON[MyJsonObject](json)
copy.asInstanceOf[MyJsonObject].map.get("myKey").get.isInstanceOf[Int] should equal(true)
}
}
}