Recently, I’ve had a bit of a SOAP baptism of fire - the project I am working on makes hundreds of SOAP calls to multiple SOAP APIs on multiple hosts. During this time I’ve encountered some common and rare problems and troubleshooting them seems to be a bit of a black art, if the number of results in Google is any measure.
To demonstrate some of these troubleshooting methods I will use a global weather SOAP service, http://www.webservicex.com/globalweather.asmx?WSDL. I’ve added the web service to vRO using the “Add a SOAP host” workflow, and then used the “Generate a new workflow from a SOAP operation” workflow to create a new workflow: GetWeather. This simple workflow runs successfully:
The SOAP Interceptor allows you to both examine, and manipulate the body of the XML SOAP request sent to the SOAP host, and the response returned to Orchestrator.
The SOAPInterceptor class has four methods that you can use to assign a function to process the request head/body, or the response head/body. It’s worth noting that you can use just one of the methods at once if required - you don’t have to define all of them.
var objInterceptor = new SOAPInterceptor(); objInterceptor.setResponseHeaderInterceptor(responseHeaderHandler); objInterceptor.setResponseBodyInterceptor(responseBodyHandler); objInterceptor.setRequestHeaderInterceptor(requestHeaderHandler); objInterceptor.setRequestBodyInterceptor(requestBodyHandler); function requestHeaderHandler(content) { // process and return the request header } function requestBodyHandler(content) { // process and return the request body } function responseHeaderHandler(content) { // Process and return the response header } function responseBodyHandler(content) { // Process and return the response body }
Now, with these functions you can begin to dig a little deeper - for example, you can write the SOAP body out to the System.log:
Now when I run the workflow, I can see the XML request body:
And if I add a handler for the response body…
I can see the XML output from the SOAP host that is returned to me:
Viewing the SOAP body is useful, and allows a certain amount of troubleshooting - but sometimes you need to see the bigger picture, and that’s where I use Fiddler. Fiddler is described by themselves as “The free web debugging proxy for any browser, system or platform” - it basically allows you to intercept and analyse local traffic a-la-WireShark, but also create a local proxy server to monitor remote traffic through.
Using Fiddler as a proxy allows you to see the full SOAP request and response.
Configuring Fiddler is really easy - once it’s downloaded and installed you can simply go through Tools > Fiddler Options… and then select the Connections tab. Tick “Allow remote computers to connect” and then specify the port you want your proxy to listen on - simple as that!
Next, add your SOAP host again, but this time specify a proxy when you do:
Recreate the workflow from the new SOAP host’s operation, or modify the existing workflow to use the new proxied SOAP host.
Now in the Fiddler console, you should be able to locate the call to the SOAP host - labelled 1 - then once it’s selected you can see the XML sent to the host (I like the SyntaxView) - labelled 2 - and the response from the SOAP host - labelled 3.
Below are some of the problems I encountered while working with SOAP hosts - I hope to add a few more later.
Orchestrator is strict about parsing responses from a SOAP host - if it does not match the WSDL it will throw all sorts of spurious errors. The chances are that if there’s a problem, it’s to do with the WSDL.
One such misleading message is below - SOAP host is not available:
By using the SOAP Interceptor to process the responseBody, I found another cryptic message which allowed me to track down the real problem “Invalid XML request body”:
Finally, after comparing the WSDL to the response (viewed using Fiddler) I found that the response contained an item that was not defined in the WSDL.
The XML generated by Orchestrator is always valid - but sometimes the SOAP host does not like the way it’s shaped - for example I had a problem with the XML namespace definitions.
Orchestrator likes to define namespaces in the nodes - e.g. the below code defines the namespace “tns” on each attribute sent to the Weather service:
One of the APIs I used was not expecting the namespace in this format, so I was able to use the SOAP interceptor object again to modify the namespace code using the String.replace() function to strip out the definition in the “tns” tags themselves, and add it to the “axis2ns” tag:
Which results in a request like this: