Simplification
This release removed a lot of functionality that should not be part of bounded but was more generic for building applications.
THIS RELEASE IS REMOVES FUNCTIONALITY
please read the following to see how you are affected.
Things that were done:
- Removed all additional required elements for Commands and Events.
- Made the event materializer filter more generic in use. Removed all build and runtime requirement handling.
- Remove compiler warnings and cleanup
- Removed explicit use of Spray-JSON
- Made version ready for release as 0.3.0
##Migration
As Runtime, BuildInfo, Compatible materialiser filter and the required use of Spray JSON are removed you need to:
The Command and Event structure changed to minimal required fields and methods.
This means that you can decide if, when and what metadata you like to use.
If you need compatibility, you need to define:
trait Id {
def idAsString: String
}
trait UserId extends Id
trait AggregateRootId extends Id
trait UserContext {
def userId: UserId
def roles: List[String]
}
trait CommandMetaData {
def timestamp: OffsetDateTime
def userContext: Option[UserContext]
val commandId: UUID = UUID.randomUUID()
}
trait MetaData {
def timestamp: OffsetDateTime
def userContext: Option[UserContext]
def causedByCommand: Option[UUID]
}
Please note that you are free to make them more application specific as there is no dependency on bounded for these.
- The AggregateRootId is now a String
Spray JSON is not required
Some helpful serialisers were written for serialising events and could also be used in your application.
If you used those, you need to add:
def jsonEnum[T <: Enumeration](enu: T): JsonFormat[T#Value] =
new JsonFormat[T#Value] {
def write(obj: T#Value): JsValue = JsString(obj.toString)
def read(json: JsValue): T#Value =
json match {
case JsString(txt) => enu.withName(txt)
case something =>
throw DeserializationException(s"Expected a value from enum $enu instead of $something")
}
}
implicit object OffsetDateTimeJsonFormat extends RootJsonFormat[OffsetDateTime] {
def write(dt: OffsetDateTime): JsValue =
JsString(
dt.truncatedTo(ChronoUnit.SECONDS)
.format(DateTimeFormatter.ISO_DATE_TIME)
)
def read(value: JsValue): OffsetDateTime =
value match {
case JsString(v) =>
OffsetDateTime.parse(v, DateTimeFormatter.ISO_DATE_TIME)
case _ =>
deserializationError(s"value $value not conform ISO8601 (yyyy-MM-dd'T'HH:mm:ssZZ) where time is optional")
}
}
implicit object JavaUUIDFormat extends RootJsonFormat[UUID] {
override def write(obj: UUID): JsValue = JsString(obj.toString)
override def read(json: JsValue): UUID =
json match {
case JsString(v) => UUID.fromString(v)
case _ =>
deserializationError(s"value $json cannot be deserialized to a UUID")
}
}
Serialisation now works with the new serialiser structure like jackson-json
Your application.conf needs to have a different section for the akka.actor
actor {
serialize-creators = off
serialize-messages = off
serialization-bindings {
"io.cafienne.bounded.aggregate.DomainEvent" = jackson-json
// enable below to check if all taskEvents have been serialized without java.io.Serializable
"java.io.Serializable" = none
}
}
Removal of BuildInfo, RuntimeInfo and Compatibility in the event materializer
You can define your own classes or remove them from your application.