Handling Fault Responses from Spring's WebServiceTemplate.marshalSendAndReceive

Kyle picture Kyle · Jan 22, 2014 · Viewed 7.7k times · Source

I'm working with Spring's WebServiceTemplate.marshalSendAndReceive(Object, WebServiceMessageCallback) method and I'm having great difficulty understanding how to handle errors properly. Right now I'm calling a SOAP service that will respond with the following message if an error has occurred internally if someone used the same unique identifier.

<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Fault>
        <faultcode>BEA-380001</faultcode>
        <faultstring>Internal Server Error</faultstring>
        <detail>
            <ns0:Fault xmlns:ns0="http://www.package.com/CommonEntities/V2" xmlns:ns2="http://www.package.com/package/schema">
                <ns0:FaultDateTime>2014-01-22T10:39:56.056-06:00</ns0:FaultDateTime>
                <ns0:FaultMessage>An application already exists for ID [987654321].</ns0:FaultMessage>
                <ns0:FaultCode>500</ns0:FaultCode>
                <ns0:FaultStack>com.package.package.exceptions.MyException: An application already exists for ID [987654321].
        at com.package.package.endpoints.MyEndpoint.createObject(MyEndpoint.java:71)
        at com.package.package.endpoints.MyEndpoint$$FastClassByCGLIB$$b46dae63.invoke(&lt;generated&gt;)
        at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
        ...More of this stack trace...

However, this message is only found by setting the org.springframework logging to trace. The message that actually makes it back out of my call to marshalSendAndReceive is the following much more generic SoapFaultClientException message.

   <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
         <faultcode>SOAP-ENV:Client</faultcode>
         <faultstring xml:lang="en">Internal Server Error</faultstring>
         <detail>
            <ns2:Fault xmlns:ns2="http://www.package.com/package/schema" xmlns:ns3="http://www.package.com/package/schema/update">
               <ns2:FaultDateTime>2014-01-22T10:39:56.787-06:00</ns2:FaultDateTime>
               <ns2:FaultMessage>Internal Server Error</ns2:FaultMessage>
               <ns2:FaultCode>2</ns2:FaultCode>
               <ns2:FaultStack>org.springframework.ws.soap.client.SoapFaultClientException: Internal Server Error
    at org.springframework.ws.soap.client.core.SoapFaultMessageResolver.resolveFault(SoapFaultMessageResolver.java:37)
    at org.springframework.ws.client.core.WebServiceTemplate.handleFault(WebServiceTemplate.java:776)
    at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:602)
    at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:539)
    at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:386)
    at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:380)
    at com.package.package.package.adapters.MyAdapter.submitObject(MyAdapter.java:48)

How can I grab the Body\Fault\details\Fault\FaultMessage from the original response and throw that as an exception in my adapter??

The actual error message from the back end request would be much more useful than a generic SoapFaultClientException and stack trace.

Package, class and object names were modified using search and replace to extract personal data. If the package or class name seems weird, that's why.

Answer

Sarvar Nishonboyev picture Sarvar Nishonboyev · Dec 16, 2018

You can implement CclientInterceptor class that allows that allows for customized client-side message interception.

Check this tutorial out: https://codenotfound.com/spring-ws-log-client-server-http-headers.html