Permalink
Browse files

Serialize events to byte arrays. Added scala check unit test.

  • Loading branch information...
1 parent 0dd3e76 commit 2b6becd2ec0d3a84e65578e850b27a806d1ea7c4 @erikrozendaal committed Mar 27, 2011
@@ -1,15 +1,29 @@
package com.zilverline.es2
package eventstore
-import net.liftweb.json._
+import net.liftweb.json.Formats
import net.liftweb.json.Serialization.{read, write}
+import java.io.{OutputStreamWriter, ByteArrayOutputStream, InputStreamReader, ByteArrayInputStream}
+import java.nio.charset.Charset
trait Serializer {
- def serialize(event: DomainEvent): String
- def deserialize(serialized: String): DomainEvent
+ def serialize(event: DomainEvent): Array[Byte]
+ def deserialize(serialized: Array[Byte]): DomainEvent
}
-class JsonSerializer(implicit formats: Formats) extends Serializer {
- def serialize(event: DomainEvent): String = write(event)
- def deserialize(serialized: String): DomainEvent = read[DomainEvent](serialized)
+class JsonSerializer(implicit formats: Formats) extends Serializer {
+ def charset = Charset.forName("UTF-8")
+ def encoder = charset.newEncoder
+ def decoder = charset.newDecoder
+
+ def serialize(event: DomainEvent): Array[Byte] = {
+ val out = new ByteArrayOutputStream()
+ write(event, new OutputStreamWriter(out, encoder))
+ out.toByteArray
+ }
+
+ def deserialize(serialized: Array[Byte]): DomainEvent = {
+ val in = new ByteArrayInputStream(serialized)
+ read[DomainEvent](new InputStreamReader(in, decoder))
+ }
}
@@ -8,8 +8,8 @@ case class EventStream(source: String, revision: Long) {
def this() = this ("", 0L)
}
-case class EventStreamRecord(id: Long, source: String, sequence: Long, event: String) extends KeyedEntity[Long] {
- def this() = this (0, "", 0L, "")
+case class EventStreamRecord(id: Long, source: String, sequence: Long, event: Array[Byte]) extends KeyedEntity[Long] {
+ def this() = this (0, "", 0L, Array.empty)
}
object SquerylEventStore extends Schema {
@@ -23,7 +23,6 @@ object SquerylEventStore extends Schema {
on(EventStreamRecords) {t =>
declare(
t.source is (dbType("varchar(36)")),
- t.event is (dbType("text")),
columns(t.source, t.sequence) are (unique))
}
}
@@ -65,12 +64,11 @@ class SquerylEventStore(serializer: Serializer) extends EventStore {
private def write = serializer.serialize _
- private def read = (s: String) =>
- try {
- serializer.deserialize(s)
- } catch {
- case e => println("failed to deserialize " + s); throw e
- }
+ private def read(s: Array[Byte]) = try {
+ serializer.deserialize(s)
+ } catch {
+ case e => println("failed to deserialize " + s); throw e
+ }
private def createEventStream(attempt: Commit) {
try {
@@ -1,5 +1,12 @@
package com.zilverline.es2
+import org.scalacheck.Arbitrary._
+import org.scalacheck.Arbitrary
+
trait TestEvent
case class ExampleEvent(content: String) extends TestEvent
case class AnotherEvent(content: String) extends TestEvent
+
+object EventGenerators {
+ implicit val arbitraryExampleEvent = Arbitrary(for (content <- arbitrary[String]) yield ExampleEvent(content))
+}
@@ -3,7 +3,8 @@ package behavior
import eventstore._
import org.specs2.execute.Result
-import org.scalacheck._, Arbitrary.arbitrary, Prop._
+import EventGenerators._
+import org.scalacheck.Prop._
class BehaviorSpec extends org.specs2.mutable.SpecificationWithJUnit with org.specs2.ScalaCheck {
@@ -14,7 +15,6 @@ class BehaviorSpec extends org.specs2.mutable.SpecificationWithJUnit with org.sp
}
implicit val scalaCheckParameters = set(minTestsOk -> 10)
- implicit val arbitraryExampleEvent = Arbitrary(for (content <- arbitrary[String]) yield ExampleEvent(content))
case class behavior() {
val EventSourceId = newIdentifier
@@ -0,0 +1,32 @@
+package com.zilverline.es2
+package eventstore
+
+import EventGenerators._
+import org.scalacheck.Prop._
+import net.liftweb.json.{Serialization, FullTypeHints}
+import java.nio.charset.{CharacterCodingException}
+
+class JsonSerializerSpec extends org.specs2.mutable.SpecificationWithJUnit with org.specs2.ScalaCheck {
+
+ "JsonSerializer" should {
+ "(de)serialize events" in serializer().test
+ "fail on JSON that cannot be encoded using UTF-8" in serializer().failOnBadUtf8
+ }
+
+ implicit val scalaCheckParameters = set(minTestsOk -> 10)
+ implicit val formats = Serialization.formats(FullTypeHints(classOf[DomainEvent] :: Nil))
+
+ case class serializer() {
+ val subject = new JsonSerializer
+
+ def test = forAll {event: ExampleEvent =>
+ subject.encoder.canEncode(event.content) ==> {
+ event == subject.deserialize(subject.serialize(event))
+ }
+ }
+
+ def failOnBadUtf8 = {
+ subject.serialize(ExampleEvent("\uDF3D")) must throwA[CharacterCodingException]
+ }
+ }
+}

0 comments on commit 2b6becd

Please sign in to comment.