4 Replies Latest reply on Apr 14, 2014 11:43 PM by Magesh Bojan

    Handling SOAPFault when consuming a SOAP service

    Artem Egorkine Newbie

      Hi,

       

      I have an external SOAP service that my application is consuming. The actual function call is done through a RefernceInvoker like:

      try {
        ReferenceInvoker i = externalSOAPService.newInvocation("method").invoke(data);
      } catch(Exception e) {
      e.printStackTrace();
      }
      

       

      If the service hits an exception on the remote side, there is a SOAPFault message coming like:

      <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
          <SOAP-ENV:Header/>
          <SOAP-ENV:Body>
              <SOAP-ENV:Fault>
                  <faultcode xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">soapenv:Server.generalException</faultcode>
                  <faultstring>INVALID_REQUEST</faultstring>
                  <faultactor>XYZService</faultactor>
                  <detail>
                      <string>Cannot process any request before user is logged in.</string>
                  </detail>
              </SOAP-ENV:Fault>
          </SOAP-ENV:Body>
      </SOAP-ENV:Envelope>
      

       

      The exception is processed in the SOAP component, and I can see it in the logs:

      09:46:55,270 DEBUG [org.switchyard.component.soap.util.SOAPUtil] javax.xml.ws.soap.SOAPFaultException: INVALID_REQUEST
        at org.apache.cxf.jaxws.DispatchImpl.mapException(DispatchImpl.java:287)
        at org.apache.cxf.jaxws.DispatchImpl.invoke(DispatchImpl.java:392)
        at org.apache.cxf.jaxws.DispatchImpl.invoke(DispatchImpl.java:243)
        at org.switchyard.component.soap.OutboundHandler.invokeService(OutboundHandler.java:329)
        ...
      

       

      However, by the time the exception reaches the catch-clause above, it is turned into a generic Excetion:

      java.lang.Exception: <?xml version="1.0" encoding="UTF-8"?><string>Cannot process any request before user is logged in.</string>
        at org.switchyard.component.bean.internal.ExchangeInvocation.createException(ExchangeInvocation.java:106)
        at org.switchyard.component.bean.internal.ExchangeInvocation.invoke(ExchangeInvocation.java:51)
        at org.switchyard.component.bean.internal.ExchangeInvocation.invoke(ExchangeInvocation.java:73)
      ...
      

       

      I would really like to process the original SOAPFault. I can do that, burt rather clumsily:

      ReferenceInvoker i = null;
      
      try {
        i = externalSOAPService.newInvocation("method");
      i.invoke(data);
      } catch(Exception e) {
        // Check for SOAP fault info
        CamelMessageProperty p = (CamelMessageProperty) i.getProperty("soap_fault_info");
        if(p != null)  {
          SOAPFaultInfo faultInfo = (SOAPFaultInfo) p.getValue();
         /* do something fancy here */
        }
      }
      

       

      Most often, I would want to re-thrown this exception and handle it elsewhere. If I were dealing with JAX-WS, there is SOAPFaultException that seems a good candidate just for that. What is a good way to handle this in SwitchYard? I may have missed it, but I don't find any good alternative. It is not a problem to roll SOAPFaultInfo into a wrapper exception like that in JAX-WS, but wouldn't it be nice if the exception raised by the invocation already contained SOAPFaultInfo data?

       

      mageshbk, I couldn't find a way to change an article into a discussion, so I'll just created a new one...