Dave Dave - 21 days ago 4
Java Question

How can a Spring Soap interceptor modify the contents of a message?

I'm trying to write an interceptor for a web service that will modify the contents of the Soap message before is sent on to the endpoint. If a client sent a message where the value of some element is 1, I want to be able to alter that element to a 2 so that, when the message arrives at the endpoint, it looks as if the client submitted a 2 instead of a 1. I'm not sure if this is a difficult task which is elluding me, or an easy task which I am making harder than it needs to be.

I have stepped through some of the Spring interceptors; but the validation and logging interceptors don't every alter the message that is in transit. The Wss4jSecurityInterceptor does add some properties to the MessageContext; but I haven't been able to leverage anything that it is doing. I have a shell of an interceptor; but nothing that is doing anything of any value.

public boolean handleRequest(MessageContext messageContext, Object endpoint)
throws Exception {

SaajSoapMessage saajSoapMessage = (SaajSoapMessage) messageContext
.getRequest();
SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();
SOAPBody soapBody = soapMessage.getSOAPBody();

return true;
}


I was hoping there was a chance that soembody else had already solved this particular problem. Any insight would be appreciated. Thanks.

Answer

Modifying the payload is a little bit tricky. The only way I've found to make this work is to use the getPayloadSource() and getPayloadResult() methods on SoapBody, which expose javax.xml.transform-friendly objects for manipulating the data.

It's annoyingly heavyweight, but you can do something like this:

Transformer identityTransform = TransformerFactory.newInstance().newTransformer();
DOMResult domResult = new DOMResult();
identityTransform.transform(soapBody.getPayloadSource(), domResult);

Node bodyContent = domResult.getNode(); // modify this

identityTransform.transform(new DOMSource(bodyContent), soapBody.getPayloadResult());

I'd love to see a better way of doing this.

Comments