neesh
neesh

Reputation: 5255

thread safety when using spring WebServiceTemplate and Jaxb2Marshaller

I am using spring WebServiceTemplate as a web service client programmatically i.e. without instantiating a spring container. I am using Jaxb2Marshaller for marshaling/unmarshaling. In my application, I create a single instance of the SaajSoapMessageFactory and one instance of Jaxb2Marshaller. I also create a single instance of the WebServiceTemplate and assign the previously created instances of SaajSoapMessageFactory and Jaxb2Marshaller.

The WebServiceTemplate I created is used in a multi threaded way i.e. multiple threads can call marshalSendAndReceive at the same time. My question is - is my configuration thread safe? I am concerned about the Jaxb2Marshaller. The javadoc says Jaxb2Marshallers are not necessarily thread safe. How can I use the Jaxb2Marshaller in a thread safe way without reinitializing the Jaxb context?

As an aside: looking at the example spring-ws configuration in the spring reference leads me to believe that the Jaxb2Marshaller is thread safe but the Javadoc seems to contradict that.

Upvotes: 7

Views: 9109

Answers (3)

Artur Linhart
Artur Linhart

Reputation: 127

The class org.springframework.oxm.jaxb.Jaxb2Marshaller is thread safe, since it creates for every marshalling event new instance of javax.xml.bind.Marshaller, see the original source code from Spring 5.2.6:

@Override
public void marshal(Object graph, Result result, @Nullable MimeContainer mimeContainer) throws XmlMappingException {
    try {
        Marshaller marshaller = createMarshaller();
        if (this.mtomEnabled && mimeContainer != null) {
            marshaller.setAttachmentMarshaller(new Jaxb2AttachmentMarshaller(mimeContainer));
        }
        if (StaxUtils.isStaxResult(result)) {
            marshalStaxResult(marshaller, graph, result);
        }
        else {
            marshaller.marshal(graph, result);
        }
    }
    catch (JAXBException ex) {
        throw convertJaxbException(ex);
    }
}

/**
 * Return a newly created JAXB marshaller.
 * <p>Note: JAXB marshallers are not necessarily thread-safe.
 * This method is public as of 5.2.
 * @since 5.2
 * @see #createUnmarshaller()
 */
public Marshaller createMarshaller() {
    try {
        Marshaller marshaller = getJaxbContext().createMarshaller();
        initJaxbMarshaller(marshaller);
        return marshaller;
    }
    catch (JAXBException ex) {
        throw convertJaxbException(ex);
    }
}

Similar situation is by Unmarshaller.

Upvotes: 2

Aaron Digulla
Aaron Digulla

Reputation: 328546

Create several Jaxb2Marshaller (say five), put them into a pool (use LinkedBlockingQueue). When you create a thread, pass it the queue.

When a thread needs one, take() one from the queue/pool. When the pool is empty, threads will block on this call.

When a thread is done using the Jaxb2Marshaller, put() it back into the queue so other threads can use it.

If you find that threads block too often waiting for a marshaller, add more to the queue (see the first step). That way, you can easily size the pool (or even make it configurable). The queue will then automatically distribute them.

Upvotes: 0

skaffman
skaffman

Reputation: 403441

The javadoc for Jaxb2Marshaller makes no mention of thread-safety one way or another, so I'm not sure why you think it's not. If it wasn't thread-safe, the javadoc would say that very clearly.

Your configuration of WebServiceTemplate, SaajSoapMessageFactory and Jaxb2Marshaller singletons is perfectly fine, and entirely thread-safe.

Upvotes: 7

Related Questions