Good judgement is the result of experience ...
Experience is the result of bad judgement. — Fred Brooks

Mapping Inheritance Cleanly with XStream

XStream is a wonderfully simple library for
mapping Java classes to XML and back. However, it has a quirk in the way
it handles inheritance: if a field refers to an object that is derived
from the field's static type, XStream adds a class attribute to the
element that corresponds to the field. Often the XML contains enough
information to decide which type of object should be unmarshalled, and so
the class element is unnecessary. However, it's not obvious how one can
stop XStream writing the class element. There is no information about how
to do it in the documentation and although the question comes up regularly
on the XStream mailing lists, I found no good answers there either. I've
finally worked out how to do it, so here's a short tutorial. Hopefully
this will stop other XStream users tearing their hair out like I did!

Let's look at some Java classes that will make XStream add a class
attribute when it marshals them to XML.

Suppose we have a calculation grid that accepts calculation requests
sent as XML messages. A calculation request contains some information
about the request (who sent it, what is the request's priority) and some
calculation parameters (market data, for example). The message can either
contain the parameters inline or a link to parameters that are stored
remotely.

We're using XStream to generate those request messages from our Java
classes. We have two classes that represent calculation parameters, one
that represents the actual parameters and one that represents a link to
remote parameters. They both implement the CalculationParameters
interface.

We have a calculation request class that carries the parameters along
with other information and doesn't care if the parameters are local
(carried within the message) or remote (linked from the message).

It is easy to configure XStream to use simple element names for classes
and convert the url field of the RemoteCalculationParameters into an
attribute named href. However, because the static type of the
CalculationRequest's parameters field is an interface,
CalculationParameters, XStream adds a class attribute to the parameters
element to identify the actual implementation that has been marshalled.
For example, RemoteCalculationParameters get marshalled like:

This looks ugly and leaks implementation details into the XML format
where they don't belong. We don't want to tie consumers of the XML to our
implementation because we will break their implementation when we refactor
our code.

The class attribute is unnecessary for our CalculationParameters types
because we can determine which concrete type to unmarshall from the
contents of XML itself: if the parameters element has an href attribute,
it represents RemoteCalculationParameters, otherwise it represents
LocalCalculationParameters. We can implement this rule as a Converter
class:

This works with multiple subclasses and with SingleValueConverters. As
long as you can determine the concrete type to be unmarshalled from the
contents of the marshalled element, you can use this technique to elide
the class attribute and get cleaner XML.

Update: I've submitted a patch to XStream that adds a
convenient API call for creating these kinds of mappings. You can apply
the patch yourself or vote for the
JIRA issue if you'd like to see it in a future version of XStream.