XStreamSerializer
by default, which uses XStream to serialize into and deserialize from XML. XStream is reasonably fast, and the result of serialization is human-readable. This makes it quite useful for logging and debugging purposes.XStreamSerializer
allows further customization if that's required. You can, for example, define aliases for specific packages, classes, or even fields. In addition to being an excellent way to shorten potentially long names, you can also use aliases when class definitions of the serialized objects change. For more information about aliases, visit the XStream website.JacksonSerializer
. This Serializer
implementation uses Jackson to serialize objects into and deserialize from JSON. It produces a more compact serialized form, while requiring those classes to stick to Jackson's conventions (or configuration). The compact format makes it ideal for events, commands, and queries, as it minimizes the storage space and package size.Serializer
and setting it within Axon's configuration for the desired infrastructure components.Serializers
come in several flavors in Axon Framework and are used for various things. Currently, you can choose between the XStreamSerializer
and JacksonSerializer
to serialize messages (commands/queries/events), tokens, snapshots and sagas in an Axon application.Configuration
API allows you to define default, message
and event
serializers, which lead to the following object-serialization break down:Serializer
is in charge of de-/serializing event messages. Events are typically stored in an event store for a long period of time. This is the main driver for choosing the event serializer implementation.Serializer
is in charge of de-/serializing the command and query messages (used in a distributed application setup). Messages are shared between nodes and typically need to be interoperable and/or compact. Take this into account when choosing the message serializer implementation.Serializer
is in charge of de-/serializing the remainder, being the tokens, snapshots and sagas. These objects are generally not shared between different applications, and most of these classes aren't expected to have some of the getters and setters that are, for example, typically required by Jackson based serializers. A flexible, general-purpose serializer like XStream is quite ideal for this purpose.Serializer
flavors are set to use the XStreamSerializer
, which internally uses XStream to serialize objects to an XML format. XML is verbose, but XStream has the major benefit of being able to serialize virtually anything.XStream and JDK 17Although XStream can "serialize virtually anything," more recent versions of the JDK impede its flexibility. This predicament comes down to XStream's reflective approach to finding out how to de-/serialize any object, which has become problematic with Java's intent to secure its internals. Hence, if you're using JDK 17, the chances are that objects (e.g., your sagas) intended for serialization require additional configuration.On some occasions configuring XStream's security settings is sufficient. Other times you will have to introduce customConverters
to de-/serialize specific types. If you prefer not to deal with specific XStream settings, it might be better to use theJacksonSerializer
throughout your Axon application.
Serializer
is configured, the event de-/serialization will be performed by the message Serializer
. In turn, if no message Serializer
is configured, the default Serializer
will take that role.XStreamSerializer
as the default and the JacksonSerializer
for all our messages:XStreamSerializer
, there are some quick wins ready to pick up. XStream allows you to configure aliases for package names and event class names. Aliases are typically much shorter (especially if you have long package names), making the serialized form of an event smaller. And since we're talking XML, each character removed from XML is twice the profit (one for the start tag, and one for the end tag)."clientId"
. The business prefers the term "customer"
, so revision 1 was created with a field called "customerId"
. This can be configured completely in XStream, using field aliases. You need to configure two aliases, in the following order: alias "customerId"
to "clientId"
and then alias "customerId"
to "customerId"
. This will tell XStream that if it encounters a field called "customerId"
, it will call the corresponding XML element "customerId"
(the second alias overrides the first). But if XStream encounters an XML element called "clientId"
, it is a known alias and will be resolved to field name "customerId"
. Check out the XStream documentation for more information.DataInputStream
and DataOutputStream
allow you to easily write the contents of the events to an output stream. The ByteArrayOutputStream
and ByteArrayInputStream
allow writing to and reading from byte arrays.SerializationAware
messages. If a SerializationAware
message is detected, its methods are used to serialize an object, instead of simply passing the payload to a serializer. This allows for performance optimizations.SerializationAware
optimization, use the MessageSerializer
class to serialize the payload and metadata of messages. All optimization logic is implemented in that class. See the JavaDoc of the MessageSerializer
for more details.EventSerializer
to something different, check out the documentation about Serializers.Serializer
's perspective means the Serializer
can ignore unknown properties. If it thus was handling a format to deserialize, it would not fail when it is incapable of finding a field / setter / constructor parameter for a given field in the serialized format.XStreamSerializer
and JacksonSerializer
can be enabled as such. How to achieve this is shown in the following snippet:ObjectMapper
to add default typing information, but the JacksonSerializer's
builder also provides a method to enable this for you. With JacksonSerializer.Builder#defaultTyping
, you will automatically enable the addition of types to the serialized format for lists and collections. Consider the following sample on how to enable default typing for the JacksonSerializer
:ContentTypeConverter
. It will search for the shortest path from type x
to type y
, perform the conversion and pass the converted value into the requested upcaster. For performance reasons, conversion will only be performed if the canUpcast
method on the receiving upcaster yields true.ContentTypeConverter
may depend on the type of serializer used. Attempting to convert a byte[]
to a dom4j Document
will not make any sense unless a Serializer
was used that writes an event as XML. Axon Framework will only use the generic content type converters (such as the one converting a String
to byte[]
or a byte[]
to InputStream
) and the converters configured on the Serializer that will be used to deserialize the message. That means if you use a JSON based serializer, you would be able to convert to and from JSON-specific formats.TipTo achieve the best performance, ensure that all upcasters in the same chain (where one's output is another's input) work on the same content type.
ContentTypeConverter
interface.XStreamSerializer
supports dom4j as well as XOM as XML document representations. The JacksonSerializer
supports Jackson's JsonNode
and ObjectNode
.