Marshalling XML using O/X Mappers
Introduction In this chapter, we will describe Spring's Object/XML Mapping support. Object/XML Mapping, or O/X mapping for short, is the act of converting an XML document to and from an object. This conversion process is also known as XML Marshalling, or XML Serialization. This chapter uses these terms interchangeably. 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. Additionally, XML Schema-based configuration is available for a number of marshallers, making the configuration even simpler. 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.
Marshaller and Unmarshaller 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.
Marshaller Spring abstracts all marshalling operations behind the org.springframework.oxm.Marshaller interface, the main methods of which is listed below. The Marshaller interface has one main 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. Result implementation Wraps XML representation DOMResult org.w3c.dom.Node SAXResult org.xml.sax.ContentHandler 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, marked with an annotation, 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.
Unmarshaller Similar to the Marshaller, there is the org.springframework.oxm.Unmarshaller interface. 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. Source implementation Wraps XML representation DOMSource org.w3c.dom.Node SAXSource org.xml.sax.InputSource, and org.xml.sax.XMLReader StreamSource java.io.File, java.io.InputStream, or java.io.Reader
Even though there are two separate marshalling interfaces (Marshaller and Unmarshaller), all implementations found in Spring-WS implement both in one class. This means that you can wire up one marshaller class and refer to it both as a marshaller and an unmarshaller in your applicationContext.xml.
XmlMappingException 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
Using Marshaller and Unmarshaller 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: 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. The Application requires both a marshaller and unmarshaller property to be set. We can do so using the following applicationContext.xml: ]]> 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 Schema-based Configuration Marshallers could be configured more concisely using tags from the OXM namespace. To make these tags available, the appropriate schema has to be referenced first in the preamble of the XML configuration file. Note the 'oxm' related text below: ]]> Currently, the following tags are available: jaxb2-marshaller xmlbeans-marshaller jibx-marshaller Each tag will be explained in its respective marshaller's section. As an example though, here is how the configuration of a JAXB2 marshaller might look like: ]]>
JAXB The JAXB binding compiler translates a W3C XML Schema into one or more Java classes, a jaxb.properties file, and possibly some resource files. JAXB also offers a way to generate a schema from annotated Java classes. Spring supports the JAXB 2.0 API as XML marshalling strategies, following the Marshaller and Unmarshaller interfaces described in . The corresponding integration classes reside in the org.springframework.oxm.jaxb package.
Jaxb2Marshaller The Jaxb2Marshaller class implements both the Spring Marshaller and Unmarshallerinterface. 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. 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: org.springframework.oxm.jaxb.Flight org.springframework.oxm.jaxb.Flights ... ]]>
XML Schema-based Configuration The jaxb2-marshaller tag configures a org.springframework.oxm.jaxb.Jaxb2Marshaller. Here is an example: ]]> Alternatively, the list of classes to bind can be provided to the marshaller via the class-to-be-bound child tag: ... ]]> Available attributes are: Attribute Description Required id the id of the marshaller no contextPath the JAXB Context path no
Castor 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.
CastorMarshaller As with JAXB, the CastorMarshaller implements both the Marshaller and Unmarshaller interface. It can be wired up as follows: ... ]]>
Mapping 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. ]]>
XMLBeans XMLBeans is an XML binding tool that has full XML Schema support, and offers full XML Infoset fidelity. It takes a different approach to that of 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.
XmlBeansMarshaller The XmlBeansMarshaller implements both the Marshaller and Unmarshaller interfaces. It can be configured as follows: ... ]]> Note that the XmlBeansMarshaller can only marshal objects of type XmlObject, and not every java.lang.Object.
XML Schema-based Configuration The xmlbeans-marshaller tag configures a org.springframework.oxm.xmlbeans.XmlBeansMarshaller. Here is an example: ]]> Available attributes are: Attribute Description Required id the id of the marshaller no options the bean name of the XmlOptions that is to be used for this marshaller. Typically a XmlOptionsFactoryBean definition no
JiBX The JiBX framework offers a solution similar to that which JDO provides 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.
JibxMarshaller The JibxMarshaller class implements both the Marshaller and Unmarshaller interface. To operate, it requires the name of the class to marshal 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 bind the Flights class: org.springframework.oxm.jibx.Flights ... ]]> A JibxMarshaller is configured for a single class. If you want to marshal multiple classes, you have to configure multiple JibxMarshallers with different targetClass property values.
XML Schema-based Configuration The jibx-marshaller tag configures a org.springframework.oxm.jibx.JibxMarshaller. Here is an example: ]]> Available attributes are: Attribute Description Required id the id of the marshaller no target-class the target class for this marshaller yes bindingName the binding name used by this marshaller no
XStream 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.
XStreamMarshaller 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: org.springframework.oxm.xstream.Flight ... ]]> By default, XStream allows for arbitrary classes to be unmarshalled, which can result in security vulnerabilities. As such, it is recommended to set the supportedClasses property on the XStreamMarshaller, like so: ... ]]> This will make sure that only the registered classes are eligible for unmarshalling. Additionally, you can register custom converters to make sure that only your supported classes can be unmarshalled. 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.