Spring WS and JAXB without a Code Generator

2010-04-28

Note: although this post mostly talks about implementing web services, the manual object-XML mapping technique described here can also be applied to WS clients.

I’d like to start by confessing that I’m very picky about programming techniques that rely on source code generators. I’m also sceptical about other kinds of compile-time tools that generate artifacts like XML files. I had my share of bad experiences with these sorts of tools, not because they are buggy or badly designed, but simply because they are not perfect.

Well, nobody’s perfect, you say? True enough. IDE auto-formatters are not perfect either. The style of code that they produce often still requires manual formatting. But it’s not a bad thing, since as a programmer I always have the final word: if I don’t like the place where that curly brace was put, or the way that lengthy statement was wrapped, I go ahead and fix it manually.

Enter the Evil Code Generators

Now, what if I don’t like some artifact produced by a generator? It can be ugly, it can be slow, it can miss the point – oh, well, there’s nothing I can do about it, because all my efforts will be overwritten during the next generation. It may be suitable for 95% cases, but what about the remaining 5%? When these tools do the work for me, they do it their way, and they won’t let me have that small customization that I need. You see, that’s one problem with code generators. They assume too much.

In my book, generators are only suitable for one-shot spawning of artifacts, or for quickly creating some throw-away demos. In practice, however, these tools are often integrated into project build lifecycle, which is bad because:

  • Generated output cannot be manually edited,
  • Generated output cannot be version controlled (at least in a meaningful way),
  • You become dependent on the generator – without it, the source won’t even compile!
  • The thought that you are not in control of your code makes you feel dizzy.

When it comes to Web Services…

…developers choose to go either the “WSDL to Java” or “Java to WSDL” route. The “to” part is usually done with some sort of generator utility, which means losing control of either the WSDL contract or the Java code. What I’d like to show in this post is a simple setup of Spring Web Services and JAXB that does not involve compile-time generation of artifacts, so that when defining your service interface you can feel completely in charge of everything: the Java, the XML, and the binding between the two.

I chose Spring WS mostly because it promotes contract-first Web Services, and JAXB2 because it’s a popular (some would say “official”) XML data binding specification. I was tempted to skip the binding part entirely and just parse/build the darn XML messages with JDOM, but then I saw that it required too much effort, especially in prospect of growing the WS interfaces.

Although I do believe that JAXB was designed to be primarily used alongside code generators like wsimport (WSDL to Java), it also works without them. What we’re going to do is:

  1. Write XML Schema for our web service
  2. Write Java classes for XML binding, with JAXB annotations
  3. Implement the endpoint
  4. Assemble everything with Spring WS configuration

The XML Schema

Create a /WEB-INF/personService.xsd file where each request and response message is expressed by an <element> and each complex type (if we need deeper structures) is represented by a <complexType>. Let’s say that our service accepts some kind of person-ID and returns the person’s name and age, where name is a complex type that consists of firstName and lastName.

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:foo="http://bar.foo"
    targetNamespace="http://bar.foo" elementFormDefault="qualified">

    <element name="GetPersonRequest">
        <complexType>
            <sequence>
                <element name="id" type="string"/>
            </sequence>
        </complexType>
    </element>

    <element name="GetPersonResponse">
        <complexType>
            <sequence>
                <element name="name" type="foo:FullName"/>
                <element name="age" type="int"/>
            </sequence>
        </complexType>
    </element>

    <complexType name="FullName">
        <sequence>
            <element name="firstName" type="string"/>
            <element name="lastName" type="string"/>
        </sequence>
    </complexType>

</schema>

The Java classes for XML binding

Now for each XML request, XML response and XML complex type we create a corresponding Java class and put JAXB annotations to bind it to XML. The Java classes that map to personService.xsd schema look like this:

@XmlRootElement(name="GetPersonRequest", namespace="http://bar.foo")
@XmlType(name="", propOrder={"id"})
@XmlAccessorType(XmlAccessType.FIELD)
public class GetPersonRequest {

    @XmlElement(name="id", namespace="http://bar.foo")
    private String id;

    /* normal getters and setters */
}

////////////////////////////////////////////////

@XmlRootElement(name="GetPersonResponse", namespace="http://bar.foo")
@XmlType(name="", propOrder={"name", "age"})
@XmlAccessorType(XmlAccessType.FIELD)
public class GetPersonResponse {

    @XmlElement(name="name", namespace="http://bar.foo")
    private FullName name;

    @XmlElement(name="age", namespace="http://bar.foo")
    private int age;

    /* normal getters and setters */
}

////////////////////////////////////////////////

@XmlType(name="FullName", namespace="http://bar.foo", propOrder={"firstName", "lastName"})
@XmlAccessorType(XmlAccessType.FIELD)
public class FullName {

    @XmlElement(name="firstName", namespace="http://bar.foo")
    private String firstName;

    @XmlElement(name="lastName", namespace="http://bar.foo")
    private String lastName;

    /* normal getters and setters */
}

Some explanation:

  • each request and response element maps to @XmlRootElement class
  • each inner element maps to @XmlElement field
  • each complex type maps to @XmlType class, where propOrder sets the order of inner elements
  • since requests and responses are also anonymous complex types, they are annotated with a nameless @XmlType
  • @XmlAccessorType(XmlAccessType.FIELD) annotation tells JAXB to access field values directly

The endpoint implementation

It’s really up to you how you’re going to implement this part. Here’s just an example of using the @PayloadRoot annotation to map incoming XML request to a handler method:

@Endpoint
public class PersonEndpoint {

    @PayloadRoot(localPart = "GetPersonRequest", namespace = "http://bar.foo")
    public GetPersonResponse getPerson(GetPersonRequest request) {
        /* implementation code */
    }
}

The assembly

Define a Jaxb2Marshaller bean and set the classesToBeBound property to an array of all @XmlRootElement classes, so that they can be recognized by the marshaller.

DefaultWsdl11Definition can be used to publish WSDL definition based on personService.xsd, as long as we follow the convention of Request/Response suffixes in XML element names. And the rest are standard Spring WS affairs. A more or less complete setup may look like this:

<!-- the endpoint implementation -->
<bean class="foo.bar.PersonEndpoint"/>

<!-- publishes WSDL contract based on the given XML schema -->
<bean id="personService" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
    <property name="schema" ref="schema">
        <bean class="org.springframework.xml.xsd.SimpleXsdSchema">
            <property name="xsd" value="/WEB-INF/personService.xsd"/>
        </bean>
    </property>
    <property name="portTypeName" value="personInterface"/>
    <property name="locationUri" value="/ws/personService"/>
    <property name="targetNamespace" value="http://bar.foo"/>
</bean>

<!-- uses annotations to map XML requests to endpoint methods -->
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping"/>

<!-- passes endpoint method arguments and returned objects to JAXB marshaller -->
<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
    <property name="marshaller" ref="jaxbMarshaller"/>
    <property name="unmarshaller" ref="jaxbMarshaller"/>
</bean>

<!-- uses JAXB annotations to marshall between XML messages and Java objects -->
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="classesToBeBound">
        <list>
            <value>foo.bar.GetPersonRequest</value>
            <value>foo.bar.GetPersonResponse</value>
        </list>
    </property>
</bean>

<!-- parses and builds SOAP messages -->
<bean class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory"/>

The dependencies

For the sake of completeness, here's a listing of relevant Maven dependencies that I used.

<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core-tiger</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-xml</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-oxm</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-oxm-tiger</artifactId>
</dependency>

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
</dependency>
<dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
</dependency>
<dependency>
    <groupId>stax</groupId>
    <artifactId>stax-api</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.ws.commons.axiom</groupId>
    <artifactId>axiom-api</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.ws.commons.axiom</groupId>
    <artifactId>axiom-impl</artifactId>
</dependency>
<dependency>
    <groupId>xml-apis</groupId>
    <artifactId>xml-apis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.ws.commons.schema</groupId>
    <artifactId>XmlSchema</artifactId>
</dependency>

For a similar no-generated-code technique applied to JAX-WS services, check out this post.

Inherit Spring Security Context in Child Threads

2010-04-04

By default, Spring Security context is bound to ThreadLocal, which may catch you by surprise in some cases involving spawned threads.

So I setup my security infrastructure to authenticate users, populate their details from database, grant them authorities, I configure AccessDecisionManager and put @Secured annotations on my business methods to assert those authorities, etc. It all works well until my business code evolves to include asynchronous invocations. Then I find myself wondering: why am I getting AuthenticationCredentialsNotFoundException in places where the user is obviously authenticated?

Turns out that when a new thread is started it knows nothing about the security context of its parent thread. So if AccessDecisionManager gets called (e.g. if a @Secured method is invoked) from within the child thread, you get a security exception.

To work around that, you should change the SecurityContextHolder strategy to use InheritableThreadLocal for storing the security context. You can do that in code:

SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL)

… or in XML configuration (which is better since you’ll only need to call the static method once during application startup):

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetClass"
        value="org.springframework.security.context.SecurityContextHolder"/>
    <property name="targetMethod" value="setStrategyName"/>
    <property name="arguments"><list><value>MODE_INHERITABLETHREADLOCAL</value></list></property>
</bean>

Note however, that you cannot share security context among sibling threads (e.g. in a thread pool). This method only works for child threads that are spawned by a thread that already contains a populated SecurityContext.