Spring Web Services: Object-XML Mapping

In this post on Spring Web Services, I will tell you something about the Object-XML Marshalling (OXM) support. In previous posts, I’ve told you about the dangers of OXM, but I also posted that:

As with O/R mapping, a good O/X mapping can certainly be extremely useful, if properly configured. So, a good SOAP stack should facilitate in this configuration, and offer something like Spring’s templates to easily convert XML to objects and vice-versa.

So, we’ve decided to add O/X Mapping to Spring-WS. This is one of the features which can also useful for REST Web services, since it has little to do with SOAP.

Marshaller and Unmarshaller

Central in Spring-WS’s are two interfaces: Marshaller and Unmarshaller. The Marshaller interface has just one method:

void marshal(Object graph, Result result)
    throws XmlMappingException, IOException;

This method will marshall the given object graph to a javax.xml.transform.Result. Result basically is an XML output stream abstraction: concrete subclasses wrap a DOM document, an OutputStream or Writer, or a SAX ContentHandler.

Likewise, the Unmarshaller interface also has one method:

Object unmarshal(Source source)
    throws XmlMappingException, IOException;

This method reads from the given javax.xml.transform.Source (an XML input stream abstraction), and returns the object read.

Implementations

Currently, we are thinking about three implementations for the two O/X interfaces: Castor, JAXB, and XMLBeans.

Most of these frameworks require some kind of configuration to operate. For instance, JAXB requires a JAXBContext, which needs a context path. Defining such a context can be quite simple, using the JaxbContextFactoryBean:

<bean id="jaxbMarshaller"
    class="org.springframework.oxm.jaxb.JaxbMarshaller">
    <property name="jaxbContext" ref="jaxbContext" />
</bean>

<bean id="jaxbUnmarshaller"
    class="org.springframework.oxm.jaxb.JaxbUnmarshaller">
    <property name="jaxbContext" ref="jaxbContext" />
</bean>

<bean id="jaxbContext"
    class="org.springframework.oxm.jaxb.JaxbContextFactoryBean">
    <property name="contextPath" value="com.example.myservice"/>
</bean>

Exceptions

Besides the I/O exception thrown by the marhsalling interfaces, there is also the XmlMappingException. This is an abstract runtime exception, which forms the root of the hierarchy of Object-XML Marshalling exceptions. It has concrete subclasses for marshalling and unmarshalling errors, and XML validation errors.

Additionally, this hierarchy follows one of the most popular features of Spring’s ORM support: it provides a unified abstraction for the various (checked) exceptions thrown by the marhalling frameworks. This means that it does not matter whether you are using Castor or JAXB: if marshalling fails, an MarshallingFailureException is thrown.

7 Comments

  1. Dan Diephouse said,

    November 23, 2005 @ 4:08

    I have a couple questions about spring web services… How does this all relate back to SOAP frameworks like axis/xfire/etc? How does the service development cycle look (wsdl first and code first)? How will jsr 181 integrate? how will ws-addressing integrate with it?

  2. James Strachan said,

    November 23, 2005 @ 9:36

    Hmmm Spring WS looks awfully like a rewrite/clone of XFire/ActiveSOAP. I don’t see how any existing frameworks are being reused - this looks like yet another WS stack rather than an abstraction layer to help reuse WS stacks.

    Maybe you should start with JSR 181 / JAX-WS - which is where its at - and work backwards rather than focussing on JBI-like APIs working with TrAX Source?

    If you want an example of a clean API for working with web services which use TrAX Source, just reuse MessageExchange and NormalizedMessage from JBI.

  3. Arjen Poutsma said,

    November 23, 2005 @ 10:41

    Hi Dan,

    This particular topic (OXM) does not relate to SOAP much. However: both SOAP stacks offer a XML marshalling engine (Axis’s Serializers and XFire’s Aegis). With the above abstraction, it would be possible to use these marshalling engines in other places, even those not related to Web services at all. And with regard to integration with regard to Web services, I’ll get back on that in a future post. At the very least, I am thinking about integration on the handler front, so that you can intermingle Axis (JAX-RPC) and XFire handlers.

    We are focussing on a contract-first development style at first. Preferably, we don’t want to create another JSR 181 implementation, because implementations already exist, for instance in XFire!

  4. Arjen Poutsma said,

    November 23, 2005 @ 11:08

    Hi James,

    Like I wrote to Dan, this particular topic is not very much related to Web services. Rather, it is about Object/XML mapping. Spring already offers an excellent abstraction for Object/Relational mapping, consisting of templates and a unified runtime exception hierarchy. What we’re trying to do here is offer something similar for OXM. For this, we are using existing frameworks only, and not creating our own XML marshalling framework.

    I’ll definately check out the JBI suggestions you made.

  5. Sébastien Blanc said,

    November 24, 2005 @ 22:45

    Hoi,

    What about also using XStream as implementation for your O/X interfaces? It’s simple, quite efficient and most of time sufficient for the applications needs.
    Anyway, the Spring WS is an excellent move and I’m waiting for it .

  6. Arjen Poutsma said,

    November 26, 2005 @ 12:28

    Hi Sébastien,

    We’ll definitely look into XStream, and possibly others too!

    Thanks for your interest!

  7. Gary Rung said,

    November 29, 2005 @ 17:16

    Hi Arjen

    Just pick up two OXM-implementations at first, one schema-first and one code-first oriented. Castor and JAXB2/XMLbeans are fine canditates. The rest will follow very soon. If the abstraction layer works the integration for other (great) OXM-implementations is trivial.

    I’m in the situation that I’m using one XML-model internally and other for exposing web services. It would be great to share same model between the ws and other system. I’m using code-first approach because my POJOs are the first class citizens in this particular system. So XMLBeans or JAXB are out of question.

    Spring OXM and WS is very very interesting move… :)

RSS feed for comments on this post