XStreamSerializerby 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.
XStreamSerializerallows 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.
Serializerimplementation 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.
Serializerand setting it within Axon's configuration for the desired infrastructure components.
Serializerscome in several flavors in Axon Framework and are used for various things. Currently, you can choose between the
JacksonSerializerto serialize messages (commands/queries/events), tokens, snapshots, deadlines and sagas in an Axon application.
ConfigurationAPI allows you to define default,
eventserializers, which lead to the following object-serialization break down:
Serializeris in charge of (de)serializing event message payload and metadata. 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.
Serializeris in charge of (de)serializing the command and query message payload and metadata (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.
Serializeris in charge of (de)serializing the remainder, being the messages (except the payload and metadata), tokens, snapshots, deadlines 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. For example, a
QueryMessageconsists of a payload and
ResponseType, which will respectively be (de)serialized using the
defaultserializer, the query request and response payload will be (de)serialized using the
messageserializer. A flexible, general-purpose serializer like XStream is quite ideal for this purpose.
Serializerflavors 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 custom
Convertersto de-/serialize specific types. If you prefer not to deal with specific XStream settings, it might be better to use the
JacksonSerializerthroughout your Axon application.
Serializeris configured, the event de-/serialization will be performed by the message
Serializer. In turn, if no message
Serializeris configured, the default
Serializerwill take that role.
XStreamSerializeras the default and the
JacksonSerializerfor 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
"clientId"and then alias
"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.
DataOutputStreamallow you to easily write the contents of the events to an output stream. The
ByteArrayInputStreamallow writing to and reading from byte arrays.
SerializationAwaremessages. If a
SerializationAwaremessage is detected, its methods are used to serialize an object, instead of simply passing the payload to a serializer. This allows for performance optimizations.
SerializationAwareoptimization, use the
MessageSerializerclass to serialize the payload and metadata of messages. All optimization logic is implemented in that class. See the JavaDoc of the
MessageSerializerfor more details.
EventSerializerto something different, check out the documentation about Serializers.
Serializer's perspective means the
Serializercan 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.
JacksonSerializercan be enabled as such. How to achieve this is shown in the following snippet:
ObjectMapperto add default typing information, but the
JacksonSerializer'sbuilder 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
ContentTypeConverter. It will search for the shortest path from type
y, perform the conversion and pass the converted value into the requested upcaster. For performance reasons, conversion will only be performed if the
canUpcastmethod on the receiving upcaster yields true.
ContentTypeConvertermay depend on the type of serializer used. Attempting to convert a
byteto a dom4j
Documentwill not make any sense unless a
Serializerwas used that writes an event as XML. Axon Framework will only use the generic content type converters (such as the one converting a
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.
XStreamSerializersupports dom4j as well as XOM as XML document representations. The