Skip to Content
Technical Articles

Fetch SOAP Fault/Error Response from Receiver in SAP Cloud Platform Integration

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

Element getDetail()

Returns the detail node.
Element getOrCreateDetail()

Returns the detail node.

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

/
13 Comments
You must be Logged on to comment or reply to a post.
  • Hi Dennis,

    Thanks for sharing! Nice catch and explanation! My impression is that SAP doesn't want to break anything including scripts so it should be safe to use this method. I hope SAP includes this in the official script examples, it would be even better.

    Regards,
    Fatih

  • Hi Dennis - Good to see the available option to process the soap fault.

    I had the similar requirement earlier , but couldn't achieve the same.

    Thanks for sharing your findings to the community

    Keep exploring and blogging.

    Cheers

    Rajesh Pasupula

     

     

     

  • Hi Dennis - Thank you for sharing!

    Converting a Node into a XML string could be done simpler in Groovy:

    import groovy.xml.*
    
    def myNodeXmlStringOut = XmlUtil.serialize(myNode)

    If you need a XML without declaration, you could write:

    import groovy.xml.*
    
    def xmlOutput = new StringWriter()
    def nodePrinter = new XmlNodePrinter(new PrintWriter(xmlOutput))
    nodePrinter.print(myNode)
    def myNodeXmlStringOut = xmlOutput.toString()

    Regards

    Thomas