Class XStreamConverter
- All Implemented Interfaces:
DescribableComponent,Converter
Converter implementation that uses an application-supplied XStream instance to convert objects into
and from the XML format that Axon Framework 4's XStreamSerializer produced.
This Converter exists for exactly one purpose: giving an Axon Framework 5 application time to let deadlines
and events that an Axon Framework 4 node scheduled, and sagas it started, run their course, instead of forcing every
one of them to fire or complete before the switch to Axon Framework 5. During a rolling upgrade, an Axon Framework 4
node may still pick up and fire a deadline or event an Axon Framework 5 node scheduled, so this Converter
must write XStream XML an Axon Framework 4 node can read, not only read it. A saga is no different here, since it
keeps handling events until it ends, so its state is both read and written back in XStream for as long as it stays
active. In practice that is Axon Framework 4 saga state (the legacy saga stores default to XStreamSerializer
when built without one), deadlines scheduled through a DeadlineManager, and events scheduled through an
EventScheduler.
Note this Converter implementation is not meant to be used for anything new. It is never registered by
default, and it should be removed from an application's configuration as soon as all data it was reading has been
drained or rewritten in the application's regular Converter format.
Construction allows "org.axonframework.**" on the given XStream instance, the same baseline Axon
Framework 4's XStreamSerializer added by default. XStream deserializes by instantiating arbitrary classes
named in the XML it reads, which is unsafe against untrusted input unless the set of types it may instantiate is
restricted. This baseline allows every class in every Axon Framework jar on the classpath, unconditionally: unlike
Axon Framework 4's XStreamSerializer, this constructor offers no disableAxonTypeSecurity()-style
opt-out, so a caller handing in an otherwise fully locked-down XStream instance still gets this baseline
widened. Callers remain responsible for allowing their own saga, deadline, and event payload classes
themselves, typically with XStream.allowTypesByWildcard(String[]) or XStream.allowTypes(Class[]),
before handing the XStream instance to this constructor.
This Converter only ever converts a single payload, metadata map, or scope descriptor at a time; it never
sees a whole message envelope. Construction aliases Metadata to the same <meta-data> element Axon
Framework 4's MetaData used, and marks UUID as an immutable type aliased to uuid, so that XML
produced by an Axon Framework 4 XStreamSerializer round-trips through this Converter unchanged.
Ported scope descriptors such as AggregateScopeDescriptor and SagaScopeDescriptor keep their Axon
Framework 4 package and class name in this module, so no further aliasing is required for those to resolve against
Axon Framework 4-written XML.
Any source type the configured ChainingContentTypeConverter can convert directly to the target type -
byte[], String, and InputStream by default - is treated as already-serialized content and
skips XStream entirely, unlike Axon Framework 4's XStreamSerializer, which always ran a payload through
XStream regardless of its Java type. Converting between two such types is therefore a plain content type conversion
around the XML, not a new XStream marshalling pass.
Running on Java 9 or later with reflective access restricted to named modules, XStream may need --add-opens
JVM arguments to reflect on types in java.base or other platform modules; see
XStream's FAQ.
Construct this Converter with a pre-configured XStream instance. Note that previous installments of
Axon Framework used to expose one that automatically aligned with pre-JDK17 reflection support. Given the current JDK
version for this project and the JDK's restrictive nature on reflection, this XStream instance is no longer
provided out of the box. Hence, it is strongly recommended to declare the XStream instance yourself,
including a full allow-list for your own application types. After that, this Converter can be passed to
builder methods of a legacy SagaStore or DeadlineManager, for example:
XStream xStream = new XStream();
xStream.allowTypesByWildcard(new String[]{"com.example.myapp.**"});
Converter xStreamConverter = new XStreamConverter(xStream);
JpaSagaStore sagaStore = JpaSagaStore.builder()
.entityManagerProvider(entityManagerProvider)
.converter(xStreamConverter)
.build();
- Since:
- 5.4.0
- Author:
- Steven van Beelen
-
Constructor Summary
ConstructorsConstructorDescriptionXStreamConverter(com.thoughtworks.xstream.XStream xStream) Deprecated, for removal: This API element is subject to removal in a future version.Constructs anXStreamConverterusing the givenxStreaminstance.XStreamConverter(com.thoughtworks.xstream.XStream xStream, ChainingContentTypeConverter converter) Deprecated, for removal: This API element is subject to removal in a future version.Constructs anXStreamConverterusing the givenxStreaminstance andconverter. -
Method Summary
Modifier and TypeMethodDescription<T> @Nullable TDeprecated, for removal: This API element is subject to removal in a future version.Converts the giveninputobject into an object of the giventargetType.voiddescribeTo(ComponentDescriptor descriptor) Deprecated, for removal: This API element is subject to removal in a future version.Describe the properties ofthis DescribableComponentwith the givendescriptor.resolveStoredType(String typeName) Deprecated, for removal: This API element is subject to removal in a future version.Resolves a type name that Axon Framework 4'sXStreamSerializerstored next to a serialized object, to the class it names, through the mapper of this converter'sXStreaminstance, as that serializer did.
-
Constructor Details
-
XStreamConverter
public XStreamConverter(com.thoughtworks.xstream.XStream xStream) Deprecated, for removal: This API element is subject to removal in a future version.Constructs anXStreamConverterusing the givenxStreaminstance.This constructor automatically allows
"org.axonframework.**"on it, so this module's ported types resolve. The caller remains responsible for allowing their own application types through the givenxStreaminstance.- Parameters:
xStream- theXStreaminstance used to convert objects into and from XML
-
XStreamConverter
@Internal public XStreamConverter(com.thoughtworks.xstream.XStream xStream, ChainingContentTypeConverter converter) Deprecated, for removal: This API element is subject to removal in a future version.Constructs anXStreamConverterusing the givenxStreaminstance andconverter.This constructor automatically allows
"org.axonframework.**"on it, so this module's ported types resolve. The caller remains responsible for allowing their own application types through the givenxStreaminstance.This constructor should only be used when a specific
ClassLoadershould be given to theChainingContentTypeConverter, to ensure it loads the right set ofContentTypeConverter ContentTypeConverters.- Parameters:
xStream- theXStreaminstance used to convert objects into and from XMLconverter- the converter used for thebyte[]/String/InputStreamcontent type conversions surrounding the XML (de)serialization
-
-
Method Details
-
convert
Deprecated, for removal: This API element is subject to removal in a future version.Description copied from interface:ConverterConverts the giveninputobject into an object of the giventargetType. -
resolveStoredType
Deprecated, for removal: This API element is subject to removal in a future version.Resolves a type name that Axon Framework 4'sXStreamSerializerstored next to a serialized object, to the class it names, through the mapper of this converter'sXStreaminstance, as that serializer did.Axon Framework 4 stored the name XStream's mapper gives a class: its alias if it has one, such as XStream's built-in
uuid,intorlong, or one the application registered, and its class name otherwise. Resolving through the same mapper turns either back into the class. A primitive type resolves to its wrapper class, as a stored value is always an object.This method is internal, as it only serves the legacy components that store a type name next to the data they convert with this converter, such as the deadline managers.
- Parameters:
typeName- the stored type name, an alias or a class name- Returns:
- the class the given
typeNamenames, or an emptyOptionalif it names none
-
describeTo
Deprecated, for removal: This API element is subject to removal in a future version.Description copied from interface:DescribableComponentDescribe the properties ofthis DescribableComponentwith the givendescriptor.Components should call the appropriate
describePropertymethods on the descriptor to register their properties. The descriptor is responsible for determining how these properties are formatted and structured in the final output.Best Practices: As a general rule, all relevant fields of a
DescribableComponentimplementation should be described in this method. However, developers have discretion to include only the fields that make sense in the context. Not every field may be meaningful for description purposes, especially internal implementation details. Furthermore, components might want to expose different information based on their current state. The final decision on what properties to include lies with the person implementing thedescribeTomethod, who should focus on providing information that is useful for understanding the component's configuration and state.Example implementation:
public void describeTo(ComponentDescriptor descriptor) { descriptor.describeProperty("name", this.name); descriptor.describeProperty("enabled", this.enabled); descriptor.describeProperty("configuration", this.configuration); // A nested component descriptor.describeProperty("handlers", this.eventHandlers); // A collection }- Specified by:
describeToin interfaceDescribableComponent- Parameters:
descriptor- The component descriptor to describethis DescribableComponentn its properties in.
-