Within the field of O/X mapping, a marshaller is responsible for serializing an object (graph) to XML. In similar fashion, an unmarshaller deserializes the XML to an object graph. This XML can take the form of a DOM document, an input or output stream, or a SAX handler.
Some of the benefits of using Spring for your O/X mapping needs are:
Ease of configuration. Spring's bean factory makes it easy to configure marshallers, without needing to construct JAXB context, JiBX binding factories, etc. The marshallers can be configured as any other bean in your application context.
Consistent Interfaces.
Spring's O/X mapping operates through two global interfaces: the
Marshaller
and
Unmarshaller
interface. These abstractions allow you to switch O/X mapping frameworks with relative ease, with little
or no changes required on the classes that do the marshalling. This approach has the additional benefit
of making it possible to do XML marshalling with a mix-and-match approach (e.g. some marshalling
performed using JAXB, other using XMLBeans) in a non-intrusive fashion, leveraging the strength of each
technology.
Consistent Exception Hierarchy.
Spring provides a conversion from exceptions from the underlying O/X mapping tool to its own exception
hierarchy with the
XmlMappingException
as the root exception. As can be expected, these runtime exceptions wrap the original exception so no
information is lost.
As stated in the introduction, a marshaller serializes an object to XML, and an unmarshaller deserializes XML stream to an object. In this section, we will describe the two Spring interfaces used for this purpose.
Spring abstracts all marshalling operations behind the
org.springframework.oxm.Marshaller
interface, which is listed below.
public interface Marshaller { /** * Marshals the object graph with the given root into the provided Result. */ void marshal(Object graph, Result result) throws XmlMappingException, IOException; }
The
Marshaller
interface has just one method, which marshals the given
object to a given
javax.xml.transform.Result
. Result is a tagging interface that
basically represents an XML output abstraction: concrete implementations wrap various XML
representations, as indicated in the table below.
javax.xml.transform.Result
implementation
| Wraps XML representation |
---|---|
javax.xml.transform.dom.DOMResult
|
org.w3c.dom.Node
|
javax.xml.transform.sax.SAXResult
|
org.xml.sax.ContentHandler
|
javax.xml.transform.stream.StreamResult
|
java.io.File
,
java.io.OutputStream
,
or
java.io.Writer
|
Although the
marshal
method accepts a plain object as its first parameter,
most
Marshaller
implementations cannot handle arbitrary objects. Instead, an
object class must be mapped in a mapping file, registered with the marshaller, or have a common
base
class. Refer to the further sections in this chapter to determine how your O/X technology of
choice
manages this.
Similar to the
Marshaller
, there is the
org.springframework.oxm.Unmarshaller
interface.
public interface Unmarshaller { /** * Unmarshals the given provided Source into an object graph. */ Object unmarshal(Source source) throws XmlMappingException, IOException; }
This interface also has one method, which reads from the given
javax.xml.transform.Source
(an XML input abstraction), and returns the
object read. As with Result, Source is a tagging interface that has three concrete implementations. Each
wraps a different XML representation, as indicated in the table below.
javax.xml.transform.Source
implementation
| Wraps XML representation |
---|---|
javax.xml.transform.dom.DOMSource
|
org.w3c.dom.Node
|
javax.xml.transform.sax.SAXSource
|
org.xml.sax.InputSource
and
org.xml.sax.XMLReader
|
javax.xml.transform.stream.StreamSource
|
java.io.File
,
java.io.InputStream
,
or
java.io.Reader
|
Even though there are two separate marshalling interfaces (
Marshaller
and
Unmarshaller
), most implementations found in Spring-WS implement both in one class.
This means that you can wire up one marshaller class and refer to it as marshaller and unmarshaller in your
applicationContext.xml
.
Spring converts exceptions from the underlying O/X mapping tool to its own exception hierarchy with the
XmlMappingException
as the root exception. As can be expected, these runtime
exceptions wrap the original exception so no information will be lost.
Additionally, the
MarshallingFailureException
and
UnmarshallingFailureException
provide a distinction between marshalling and
unmarshalling operations, even though the underlying O/X mapping tool does not do so.
The O/X Mapping exception hierarchy is shown in the following figure:
O/X Mapping exception hierarchy
Spring's OXM can be used for a wide variety of situations. In the following example, we will use it to marshal the settings of a Spring-managed application as an XML file. We will use a simple JavaBean to represent the settings:
public class Settings { private boolean fooEnabled; public boolean isFooEnabled() { return fooEnabled; } public void setFooEnabled(boolean fooEnabled) { this.fooEnabled = fooEnabled; } }
The application class uses this bean to store its settings. Besides a main method, the class has two
methods:
saveSettings
saves the settings bean to a file named
settings.xml
, and
loadSettings
loads these settings again. A
main
method constructs a Spring application context, and calls these two methods.
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.oxm.Marshaller; import org.springframework.oxm.Unmarshaller; public class Application { private static final String FILE_NAME = "settings.xml"; private Settings settings = new Settings(); private Marshaller marshaller; private Unmarshaller unmarshaller; public void setMarshaller(Marshaller marshaller) { this.marshaller = marshaller; } public void setUnmarshaller(Unmarshaller unmarshaller) { this.unmarshaller = unmarshaller; } public void saveSettings() throws IOException { FileOutputStream os = null; try { os = new FileOutputStream(FILE_NAME); this.marshaller.marshal(settings, new StreamResult(os)); } finally { if (os != null) { os.close(); } } } public void loadSettings() throws IOException { FileInputStream is = null; try { is = new FileInputStream(FILE_NAME); this.settings = (Settings) this.unmarshaller.unmarshal(new StreamSource(is)); } finally { if (is != null) { is.close(); } } } public static void main(String[] args) throws IOException { ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Application application = (Application) appContext.getBean("application"); application.saveSettings(); application.loadSettings(); } }
The
Application
requires both a
marshaller
and
unmarshaller
property to be set. We can do so using the following
applicationContext.xml
:
<beans> <bean id="application" class="Application"> <property name="marshaller" ref="castorMarshaller" /> <property name="unmarshaller" ref="castorMarshaller" /> </bean> <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/> </beans>
This application context uses Castor, but we could have used any of the other marshaller instances described
later in this chapter. Note that Castor does not require any further configuration by default, so the bean
definition is rather simple. Also note that the
CastorMarshaller
implements both
Marshaller
and
Unmarshaller
, so we can refer to the
castorMarshaller
bean in both the
marshaller
and
unmarshaller
property of the application.
This sample application produces the following
settings.xml
file:
<?xml version="1.0" encoding="UTF-8"?> <settings foo-enabled="false"/>
The JAXB binding compiler translates a W3C XML Schema into one or more Java classes, a
jaxb.properties
file, and possibly other files, depending on the specific implementation of JAXB. Alternatively, JAXB2
offers a way to generate a schema from annotated Java classes.
Spring supports both the JAXB 1.0 as the JAXB 2.0 API as XML marshalling strategy, following the
Marshaller
and
Unmarshaller
interfaces described in
Section 8.2, “Marshaller and Unmarshaller”
. The corresponding integration classes reside in the
org.springframework.oxm.jaxb
package.
The
Jaxb1Marshaller
class implements both the Spring
Marshaller
and
Unmarshaller
interface. It requires a
context path to operate, which you can set using the
contextPath
property. The
context path is a list of colon (:) separated Java package names that contain schema derived classes.
The marshaller has an additional
validating
property which defines whether to
validate invoming XML.
The next sample bean configuration shows how to configure a
JaxbMarshaller
using the classes generated to
org.springframework.ws.samples.airline.schema
.
<beans> <bean id="jaxb1Marshaller" class="org.springframework.oxm.jaxb.Jaxb1Marshaller"> <property name="contextPath" value="org.springframework.ws.samples.airline.schema"/> </bean> ... </beans>
The
Jaxb2Marshaller
can be configured using the same
contextPath
property as the
Jaxb1Marshaller
. However, it also offers a
classesToBeBound
property, which allows you to set an array of classes to be supported by the marshaller. Schema
validation is performed by specifying one or more schema resource to the bean, like so:
<beans> <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <list> <value>org.springframework.oxm.jaxb.Flight</value> <value>org.springframework.oxm.jaxb.Flights</value> </list> </property> <property name="schema" value="classpath:org/springframework/oxm/schema.xsd"/> </bean> ... </beans>
Castor XML mapping is an open source XML binding framework. It allows you to transform the data contained in a java object model into/from an XML document. By default, it does not require any further configuration, though a mapping file can be used to have more control over the behavior of Castor.
For more information on Castor, refer to the
Castor web site
. The Spring integration classes reside in the
org.springframework.oxm.castor
package.
As with JAXB, the
CastorMarshaller
implements both the
Marshaller
and
Unmarshaller
interface. It can be wired up
as follows:
<beans> <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" /> ... </beans>
Although it is possible to rely on Castor's default marshalling behavior, it might be necessary to have more control over it. This can be accomplished using a Castor mapping file. For more information, refer to Castor XML Mapping .
The mapping can be set using the
mappingLocation
resource property, indicated
below with a classpath resource.
<beans> <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" > <property name="mappingLocation" value="classpath:mapping.xml" /> </bean> </beans>
XMLBeans is an XML binding tool that has full XML Schema support, and offers full XML Infoset fidelity. It
takes a different approach that most other O/X mapping frameworks, in that all classes that are
generated from an XML Schema are all derived from
XmlObject
, and contain XML binding
information in them.
For more information on XMLBeans, refer to the
XMLBeans
web site
. The Spring-WS integration classes reside in the
org.springframework.oxm.xmlbeans
package.
The
XmlBeansMarshaller
implements both the
Marshaller
and
Unmarshaller
interface. It can be wired up as follows:
<beans> <bean id="xmlBeansMarshaller" class="org.springframework.oxm.xmlbeans.XmlBeansMarshaller" /> ... </beans>
Note that the
XmlBeansMarshaller
can only marshal objects of type
XmlObject
, and not every
java.lang.Object
.
The JiBX framework offers a solution similar to JDO does for ORM: a binding definition defines the rules for how your Java objects are converted to or from XML. After preparing the binding and compiling the classes, a JiBX binding compiler enhances the class files, and adds code to handle converting instances of the classes from or to XML.
For more information on JiBX, refer to the
JiBX web
site
. The Spring integration classes reside in the
org.springframework.oxm.jibx
package.
The
JibxMarshaller
class implements both the
Marshaller
and
Unmarshaller
interface. To operate, it requires the name of the class to
marshall in, which you can set using the
targetClass
property. Optionally, you can
set the binding name using the
bindingName
property. In the next sample, we refer to
the
flightsBindingFactory
defined in the previous bean definition.
<beans> <bean id="jibxFlightsMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller"> <property name="targetClass">org.springframework.oxm.jibx.Flights</property> </bean> ...
A
JibxMarshaller
is configured for a single class. If you want to marshal
multiple classes, you have to configure multiple
JibxMarshaller
s with
different
targetClass
es.
XStream is a simple library to serialize objects to XML and back again. It does not require any mapping, and generates clean XML.
For more information on XStream, refer to the
XStream
web site
. The Spring integration classes reside in the
org.springframework.oxm.xstream
package.
The
XStreamMarshaller
does not require any configuration, and can be configured
in an application context directly. To further customize the XML, you can set an
alias map
, which consists of string aliases mapped to classes:
<beans> <bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"> <property name="aliases"> <props> <prop key="Flight">org.springframework.oxm.xstream.Flight</prop> </props> </property> </bean> ... </beans>
Note that XStream is an XML serialization library, not a data binding library. Therefore, it has limited namespace support. As such, it is rather unsuitable for usage within Web services.