Protected

If you are sending messages to a remote Actor/Active Object and these messages are implementing one of the predefined interfaces/traits in the 'se.scalablesolutions.akka.serialization.Serialization.*' 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
Note however that if you are using one of the Serialization interfaces then you don’t have to do anything else in regard to sending remote messages.
The ones currently supported are (besides the default which is regular Java serialization):
Apart from the above, Akka also supports Scala object serialization through SJSON that implements APIs similar to 'se.scalablesolutions.akka.serialization.Serializer.*'. See the section on SJSON below for details.
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.
Here is an example of how it can be used:
Use the se.scalablesolutions.akka.serialization.Serialization.ScalaJSON base class with its toJSON method. Akka’s Scala JSON is based upon the SJSON library.
For your POJOs to be able to serialize themselves you have to extend the ScalaJSON trait.
Use se.scalablesolutions.akka.serialization.Serializer.ScalaJSON to do generic JSON serialization, e.g. serialize object that does not extend ScalaJSON using the JSON serializer.
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.
Example: I have a Scala object as ..
where Address is a custom class defined by the user. Using SJSON, I can store it as JSON and retrieve as plain old Scala object. Here’s the simple assertion that validates the invariant. Note that during de-serialziation, the class name is specified. Hence what it gives back is an instance of Address.
There are situations, particularly when writing generic persistence libraries in Akka, when the exact class is not known during de-serialization. Using SJSON I can get it as AnyRef or Nothing ..
or just as ..
What you get back from is a JsValue, an abstraction of the JSON object model. For details of JsValueimplementation, refer to dispatch-json that SJSON uses as the underlying JSON parser implementation. Once I have the JsValue model, I can use use extractors to get back individual attributes ..
SJSON supports serialization of Scala objects that have other embedded objects. Suppose you have the following Scala classes .. Here Contact has an embedded Address Map ..
When this will be serialized out, the property name will be changed.
When serializing objects, some of the properties can be ignored declaratively. Consider the following class declaration:
The annotation @JSONProperty can be used to selectively ignore fields. When I serialize a Journal object out and then back in, the content of issn field will be null.
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}.
Consider the following Scala class:
Because of erasure, you need to add the type hint declaratively through the annotation @JSONTypeHint that
SJSON will pick up during serialization. No we can say:
With optional generic data members, we need to provide the hint to SJSON through another [email protected].
Serialization works ok with optional members annotated as above.
You can also specify a custom ClassLoader while using SJSON serializer:
Use the se.scalablesolutions.akka.serialization.Serialization.JavaJSON base class with its toJSONmethod. Akka’s Java JSON is based upon the Jackson library.
For your POJOs to be able to serialize themselves you have to extend the JavaJSON trait.
Use the se.scalablesolutions.akka.serialization.SerializerFactory.getJavaJSON to do generic JSONserialization, e.g. serialize object that does not extend JavaJSON using the JSON serializer.
To serialize Scala structures you can use SBinary serializer. SBinary can serialize all primitives and most default Scala datastructures; such as List, Tuple, Map, Set, BigInt etc.
Here is an example of using the se.scalablesolutions.akka.serialization.Serializer.SBinary serializer to serialize standard Scala library objects.
If you need to serialize your own user-defined objects then you have to do three things:
Here is an example:
You can also use Google Protocol Buffers to serialize you objects. For this we provide these.scalablesolutions.akka.serialization.Serializer.Protobuf serializer. Protobuf currently only has a Java serialization format but that works fine to use from within Scala code.
Here is the same example as above but in Java.

Serialization
If you are sending messages to a remote Actor/Active Object and these messages are implementing one of the predefined interfaces/traits in the 'se.scalablesolutions.akka.serialization.Serialization.*' 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
- se.scalablesolutions.akka.serialization.Serialization.*
has a matching serializer in - se.scalablesolutions.akka.serialization.Serializer.*.
Note however that if you are using one of the Serialization interfaces then you don’t have to do anything else in regard to sending remote messages.
The ones currently supported are (besides the default which is regular Java serialization):
- ScalaJON (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 that implements APIs similar to 'se.scalablesolutions.akka.serialization.Serializer.*'. See the section on SJSON below for details.
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.
Here is an example of how it can be used:
import se.scalablesolutions.akka.serialization.Compression val bytes: Array[Byte] = ... val compressBytes = Compression.LZF.compress(bytes) val uncompressBytes = Compression.LZF.uncompress(compressBytes)
JSON: Scala
Use the se.scalablesolutions.akka.serialization.Serialization.ScalaJSON base class with its toJSON method. Akka’s Scala JSON is based upon the SJSON library.
For your POJOs to be able to serialize themselves you have to extend the ScalaJSON trait.
case class MyMessage(val id: String, val value: Tuple2[String, Int]) extends ScalaJSON val message = MyMessage("id", ("hello", 34)) val json = message.toJSON val messageCopy = Serializer.ScalaJSON.in(json)
Use se.scalablesolutions.akka.serialization.Serializer.ScalaJSON to do generic JSON serialization, e.g. serialize object that does not extend ScalaJSON using the JSON serializer.
val foo = new Foo val json = Serializer.ScalaJSON.out(foo) val fooCopy = Serializer.ScalaJSON.in(json).asInstanceOf[Foo]
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.
Example: I have a Scala object as ..
val addr = Address("Market Street", "San Francisco", "956871")
where Address is a custom class defined by the user. Using SJSON, I can store it as JSON and retrieve as plain old Scala object. Here’s the simple assertion that validates the invariant. Note that during de-serialziation, the class name is specified. Hence what it gives back is an instance of Address.
addr should equal( serializer.in[Address](serializer.out(addr)))
There are situations, particularly when writing generic persistence libraries in Akka, when the exact class is not known during de-serialization. Using SJSON I can get it as AnyRef or Nothing ..
serializer.in[AnyRef](serializer.out(addr))
or just as ..
serializer.in(serializer.out(addr))
What you get back from is a JsValue, an abstraction of the JSON object model. For details of JsValueimplementation, refer to dispatch-json that SJSON uses as the underlying JSON parser implementation. Once I have the JsValue model, I can use use extractors to get back individual attributes ..
val a = serializer.in[AnyRef](serializer.out(addr)) // use extractors val c = 'city ? str val c(_city) = a _city should equal("San Francisco") val s = 'street ? str val s(_street) = a _street should equal("Market Street") val z = 'zip ? str val z(_zip) = a _zip should equal("956871")
Serialization of Embedded Objects
SJSON supports serialization of Scala objects that have other embedded objects. Suppose you have the following Scala classes .. Here Contact has an embedded Address Map ..
@BeanInfo case class Contact(name: String, @JSONTypeHint(classOf[Address]) addresses: Map[String, Address]) { override def toString = "name = " + name + " addresses = " + addresses.map(a => a._1 + ":" + a._2.toString).mkString(",") } @BeanInfo case class Address(street: String, city: String, zip: String) { override def toString = "address = " + street + "/" + city + "/" + zip }With SJSON, I can do the following:
val a1 = Address("Market Street", "San Francisco", "956871") val a2 = Address("Monroe Street", "Denver", "80231") val a3 = Address("North Street", "Atlanta", "987671") val c = Contact("Bob", Map("residence" -> a1, "office" -> a2, "club" -> a3)) val co = serializer.out(c) // with class specified c should equal(serializer.in[Contact](co)) // no class specified val a = serializer.in[AnyRef](co) // extract name val n = 'name ? str val n(_name) = a "Bob" should equal(_name) // extract addresses val addrs = 'addresses ? obj val addrs(_addresses) = a // extract residence from addresses val res = 'residence ? obj val res(_raddr) = _addresses // make an Address bean out of _raddr val address = JsBean.fromJSON(_raddr, Some(classOf[Address])) a1 should equal(address) object r { def ># [T](f: JsF[T]) = f(a.asInstanceOf[JsValue]) } // still better: chain 'em up "Market Street" should equal( (r ># { ('addresses ? obj) andThen ('residence ? obj) andThen ('street ? str) }))
Changing property names during serialization
@BeanInfo case class Book(id: Number, title: String, @JSONProperty("ISBN") isbn: String) { override def toString = "id = " + id + " title = " + title + " isbn = " + isbn }
When this will be serialized out, the property name will be changed.
val b = new Book(100, "A Beautiful Mind", "012-456372") val jsBook = Js(JsBean.toJSON(b)) val expected_book_map = Map( JsString("id") -> JsNumber(100), JsString("title") -> JsString("A Beautiful Mind"), JsString("ISBN") -> JsString("012-456372") )
Serialization with ignore properties
When serializing objects, some of the properties can be ignored declaratively. Consider the following class declaration:
@BeanInfo case class Journal(id: BigDecimal, title: String, author: String, @JSONProperty {val ignore = true} issn: String) { override def toString = "Journal: " + id + "/" + title + "/" + author + (issn match { case null => "" case _ => "/" + issn }) }
The annotation @JSONProperty can be used to selectively ignore fields. When I serialize a Journal object out and then back in, the content of issn field will be null.
it("should ignore issn field") { val j = Journal(100, "IEEE Computer", "Alex Payne", "012-456372") serializer.in[Journal](serializer.out(j)).asInstanceOf[Journal].issn should equal(null) }
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
Consider the following Scala class:
@BeanInfo case class Contact(name: String, @JSONTypeHint(classOf[Address]) addresses: Map[String, Address]) { override def toString = "name = " + name + " addresses = " + addresses.map(a => a._1 + ":" + a._2.toString).mkString(",") }
Because of erasure, you need to add the type hint declaratively through the annotation @JSONTypeHint that
SJSON will pick up during serialization. No we can say:
val c = Contact("Bob", Map("residence" -> a1, "office" -> a2, "club" -> a3)) val co = serializer.out(c) it("should give an instance of Contact") { c should equal(serializer.in[Contact](co)) }
With optional generic data members, we need to provide the hint to SJSON through another [email protected].
@BeanInfo case class ContactWithOptionalAddr(name: String, @JSONTypeHint(classOf[Address]) @OptionTypeHint(classOf[Map[_,_]]) addresses: Option[Map[String, Address]]) { override def toString = "name = " + name + " " + (addresses match { case None => "" case Some(ad) => " addresses = " + ad.map(a => a._1 + ":" + a._2.toString).mkString(",") }) }
Serialization works ok with optional members annotated as above.
describe("Bean with optional bean member serialization") { it("should serialize with Option defined") { val c = new ContactWithOptionalAddr("Debasish Ghosh", Some(Map("primary" -> new Address("10 Market Street", "San Francisco, CA", "94111"), "secondary" -> new Address("3300 Tamarac Drive", "Denver, CO", "98301")))) c should equal( serializer.in[ContactWithOptionalAddr](serializer.out(c))) } }
You can also specify a custom ClassLoader while using SJSON serializer:
object SJSON { val classLoader = //.. specify a custom classloader } import SJSON._ serializer.out(..) //..
JSON: Java
Use the se.scalablesolutions.akka.serialization.Serialization.JavaJSON base class with its toJSONmethod. Akka’s Java JSON is based upon the Jackson library.
For your POJOs to be able to serialize themselves you have to extend the JavaJSON trait.
class MyMessage extends JavaJSON { private String name = null; public MyMessage(String name) { this.name = name; } public String getName() { return name; } } MyMessage message = new MyMessage("json"); String json = message.toJSON(); SerializerFactory factory = new SerializerFactory(); MyMessage messageCopy = factory.getJavaJSON().in(json);
Use the se.scalablesolutions.akka.serialization.SerializerFactory.getJavaJSON to do generic JSONserialization, e.g. serialize object that does not extend JavaJSON using the JSON serializer.
Foo foo = new Foo(); SerializerFactory factory = new SerializerFactory(); String json = factory.getJavaJSON().out(foo); Foo fooCopy = factory.getJavaJSON().in(json, Foo.class);
SBinary: Scala
To serialize Scala structures you can use SBinary serializer. SBinary can serialize all primitives and most default Scala datastructures; such as List, Tuple, Map, Set, BigInt etc.
Here is an example of using the se.scalablesolutions.akka.serialization.Serializer.SBinary serializer to serialize standard Scala library objects.
import sbinary.DefaultProtocol._ // you always need to import these implicits val users = List(("user1", "passwd1"), ("user2", "passwd2"), ("user3", "passwd3")) val bytes = Serializer.SBinary.out(users) val usersCopy: List[Tuple2[String, String]]] = Serializer.SBinary.in(bytes)
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:
- fromBytes(bytes: Array[Byte])[T]
- toBytes: Array[Byte]
- 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, usingwrite[FieldType](out, value.field).
Here is an example:
case class User(val usernamePassword: Tuple2[String, String], val email: String, val age: Int) extends Serializable.SBinary[User] { import sbinary.DefaultProtocol._ def this() = this(null, null, 0) implicit object UserFormat extends Format[User] { def reads(in : Input) = User( read[Tuple2[String, String]](in), read[String](in), read[Int](in)) def writes(out: Output, value: User) = { write[Tuple2[String, String]](out, value.usernamePassword) write[String](out, value.email) write[Int](out, value.age) } } def fromBytes(bytes: Array[Byte]) = fromByteArray[User](bytes) def toBytes: Array[Byte] = toByteArray(this) }
Protobuf: Scala
You can also use Google Protocol Buffers to serialize you objects. For this we provide these.scalablesolutions.akka.serialization.Serializer.Protobuf serializer. Protobuf currently only has a Java serialization format but that works fine to use from within Scala code.
import com.google.protobuf.Message case class User(username: String, password: String, email: String) extends Serializable.Protobuf[User] { def getMessage: Message = ... // Return the Protobuf generated Message class }
// Use Protobuf Builder to build a message val pojo = ProtobufPOJO.getDefaultInstance.toBuilder.setId(1).setName("protobuf").setStatus(true).build val bytes = pojo.toByteArray val pojoCopy = Serializer.Protobuf.in(bytes, classOf[ProtobufPOJO])
Protobuf: Java
Here is the same example as above but in Java.
// Use Protobuf Builder to build a message ProtobufPOJO pojo = ProtobufPOJO.getDefaultInstance().toBuilder().setId(1).setName("protobuf").setStatus(true).build(); byte[] bytes = pojo.toByteArray SerializerFactory factory = new SerializerFactory(); Object pojoCopy = factory.getProtobuf().in(bytes, pojo.getClass());