Skip to Content
Technical Articles
Author's profile photo Dennis Sentler

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

Assigned tags

      13 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Fatih Pense
      Fatih Pense

      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

      Author's profile photo Dennis Sentler
      Dennis Sentler
      Blog Post Author

      Thanks for supporting me on my first blog post Fatih Pense

      Author's profile photo Fatih Pense
      Fatih Pense

      Hi Dennis, great start to your blogging journey! I'm eagerly waiting for more 😉 Feel free to connect if I can help with anything, from discussion to proof-reading 🙂

      I have included this script to my community repo here with a reference to this blog post: https://github.com/pizug/cpi-groovy-examples/tree/master/get-soap-error-body

      Best regards,
      Fatih

      Author's profile photo Niharika Salla
      Niharika Salla

      Do You have any sample code in groovy to return the root node as output.

      Author's profile photo Fatih Pense
      Fatih Pense

      Hi Niharika, if you need the XML as it is, I think you still need to use HTTP adapter. This exception class parses the SOAP Exception.

      Regards,
      Fatih

      Author's profile photo Niharika Salla
      Niharika Salla

      Hi Fatih,

       

      I just want to read the parent node coming from the soap service. I have a link that explains my requirement but it is in java and I need it in groovy. I am pretty new to groovy to I am missing some methods to add.

       

      https://www.roseindia.net/xml/dom/GetRootNode.shtml

       

      Could You see if I could get any help on code.

       

       

      Author's profile photo Fatih Pense
      Fatih Pense

      Hi Niharika, if you need the XML root element, I think you have to change the receiver adapter to HTTP. I'm not aware of any other solution. Then when an exception happens you can use another script in the exception subprocess.

      I have documented the steps to change receiver from SOAP->HTTP here:
      https://answers.sap.com/questions/13028235/fetch-soap-fault-message-in-receiver-in-cpi.html

      You can also search for similar questions or create a new question for better visibility.
      https://community.sap.com/search/?ct=qa&q=cpi%20soap%20exception%20body&qt=all

      Regards,
      Fatih

      Author's profile photo Sriprasad Shivaram Bhat
      Sriprasad Shivaram Bhat

      Hello Dennis,

      Nice write up and helpful one for quick references!

      Regards,

      Sriprasad Shivaram Bhat

      Author's profile photo Dennis Sentler
      Dennis Sentler
      Blog Post Author

      Thank you

      Author's profile photo Rajesh Pasupula
      Rajesh Pasupula

      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

       

       

       

      Author's profile photo Thomas Buerki
      Thomas Buerki

      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

      Author's profile photo Dennis Sentler
      Dennis Sentler
      Blog Post Author

      Hi Thomas,

      I’m not very familiar with groovy libraries, so thank you very much for your comment.
      It works like a charm!
      Do you mind, if I improve the blog post with your code?

      Thanks Dennis

      Author's profile photo Thomas Buerki
      Thomas Buerki

      Hi Dennis

      No, please use my code if you want to use it in your blog post.