开发者

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 rein开发者_运维技巧itializing 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.


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜