Handling SOAPFault when consuming a SOAP service
arteme Apr 9, 2014 4:56 AMHi,
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...