views:

55

answers:

2

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.

+1  A: 

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.

skaffman
Thanks. You're right - it is not as straight forward as one might hope. I actually solved my problem in another fashion. While it does not address my original question directly - it solved my current problem.
Dave
A: 

I realized that it was easer to alter the request at a later point. I did not need to modify the original SOAP message, so long as I was able to modify the data before it reached my endpoint.

The endpoints I am working with all extend AbstractDom4jPayloadEndpoint - so I wrapped these endpoints in a proxy that allowed me to modify the request element before proceeding to my endpoint. i.e.:

public class MyProxyEndpoint extends AbstractDom4jPayloadEndpoint

    @Override
    protected Element invokeInternal( 
        Element requestElement,
        Document responseDocument ) throws Exception
    {
        if( requestElement != null )
        {
            // alter request element
        }

        return ( Element ) this.invokeMethod.invoke( 
            this.target,
            requestElement,
            responseDocument );
    }
Dave