Introduction
If you are working on integration development for Cloud Platform Integration (CPI), you have probably already used the SOAP receiver adapter with the request-reply pattern.
As long as everything works fine on the receiver side, it works fine on the CPI side, I get the SOAP response and can work with it. But in case of server errors, I noticed an undesirable behavior. SOAP Faults or error messages were not accessible for me, in the error subprocesses. The message body was simply empty, after the request-reply step.
Context
In my case, I have set up a web service call to a SOAP endpoint from SAP Process Orchestration (PO). The endpoint is configured to send an error message with details to the sender when an error occurs.
To accomplish this on SAP PO site, follow this SAP Note
2293430 - Processing error response at sender SOAP adapter - SAP ONE Support Launchpad
In the CPI I want to process these error details and display them to the responsible user. This did not work out of the box, the message text was always just empty after the error occurred.
First Attempts
The only thing I got was a generic message "Server Error" from the exchange object with the
${exception.message} operation.
Next I've tried a script for http error response extraction from
${property.CamelExceptionCaught} , mentioned on this help site:
Script Example for Exception Handling in HTTP Receiver - SAP Help Portal
But this script works only with HTTP exceptions, like
org.apache.camel.component.ahc.AhcOperationFailedException
It doesn't work because we captured another object in this property during runtime. It is not
AhcOperationFailedException, but an object of
SoapFault class.
Adjusted Solution
I've stickend to the solution with a script and tried to adjust it to SOAP Fault objects.
--------------------------------------------------------------------
org.apache.cxf.binding.soap
Class SoapFault extends Fault
ref.:
SoapFault (Apache CXF JavaDoc 3.2.0 API)
--------------------------------------------------------------------
Those both functions provide an org.w3c.dom.
Element, which is (unfortunately) not parsable by the CPI.
You can set this Element as a new body and you will see the message body during trace.
But operations (like XPath, Content Modifier) won't work on your new message body. You will receive an error message like:
org.apache.camel.NoTypeConversionAvailableException:
No type converter available to convert from type: com.sun.org.apache.xerces.internal.dom.ElementNSImpl
to the required type: javax.xml.transform.sax.SAXSource
Serializing the org.w3c.dom.
Element object to a simple
String and set it as the message body, works great for the CPI.
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import org.w3c.dom.Node;
import groovy.xml.*
def Message processData(Message message) {
def map = message.getProperties();
def ex = map.get("CamelExceptionCaught");
if (ex.getClass().getCanonicalName().equals("org.apache.cxf.binding.soap.SoapFault")) {
def xml = XmlUtil.serialize(ex.getOrCreateDetail());
message.setBody(xml);
}
return message;
}
- Improvements by thomas.buerki
Conclusion
This script gives me the ability to process the SOAP fault response with the usual XPath operations and even mappings. I can now distinguish between nodes and evaluate them individually.
I hope this script helps someone who is struggling with the same problem.
I am open for improvements, opinions and questions.
Cheers
Dennis Sentler