Advertisements
RSS

Tag Archives: soapUI

How to dynamically generate XML Request in ReadyAPI / SOAPui ?

We have a functional test where we use a SOAP Request to start the processing of a couple files based on a URL in the request. For a negative test (all corrupt files) we got a batch of 500 files. So to prevent a lot of copy/paste work in my SOAP Request I wanted to generate the request dynamically. I did this before, couldn’t find/remember my own example so eventually when I got it working decided to share and store it here.

First some housekeeping

I always do some housekeeping in the init groovy step of my tests to generate an unique id (for correlation, etc etc) and more.

//Generate unique id - sequence
def v_sequence = new Date().time.toString()
 
// testRunner.testCase.setPropertyValue("sequence", v_sequence)
testRunner.testCase.testSuite.project.setPropertyValue("v_sequence", v_sequence)
 
// empty some variables
testRunner.testCase.testSuite.project.setPropertyValue("XML", "")
testRunner.testCase.testSuite.project.setPropertyValue("teller", "1")

Then the basic dataloop

Using an external datasource is the way to go if we want to load data. In the example I only use 1 field (url) in a text file with 500 lines:

The DataSource Loop function makes it possible to go back to the Groovy script “Generate XML Request” to build the request line by line.

The Groovy magic

Here is the groovy script that holds the logic. For each url in the dataloop we create an Document XML complex element which we add to the list of

import groovy.xml.StreamingMarkupBuilder
import groovy.xml.XmlUtil
import groovy.util.XmlSlurper
 
def sequence = context.expand( '${#Project#v_sequence}' )
def url = context.expand( '${DataSource#url}' )
def datumtijd = new Date().format("yyyy-MM-dd'T'HH:mm:ss")
def teller = context.expand( '${#Project#teller}' )
 
log.info('sequence = ' + sequence)
log.info('url = ' + url)
 
def filename = url.split('/').last()
log.info('filename = ' + filename)          
           
// Define all your namespaces here
// def nameSpacesMap = [soapenv: 'http://schemas.xmlsoap.org/soap/envelope/',ns: 'nl.rubix.ohmy',]
def builder = new StreamingMarkupBuilder()
builder.encoding ='utf-8'
def xmlDocument = builder.bind
{
//          namespaces << nameSpacesMap
            // use it like ns.element            
            Document
            {
                        Id('DOC.' + sequence + '.' + teller);
                        Name(filename);                        
                        Date(datumtijd);
                        Url(url);
            }
            Document       
}
 
// XML buildup to get rid of irritating XML version string which probably can be done much nicer
def v_document = XmlUtil.serialize(xmlDocument);
v_document = v_document.substring(39)
log.info("XML = " + v_document);
def origineelXML = context.expand( '${#Project#XML}' )
origineelXML = origineelXML + v_document
testRunner.testCase.testSuite.project.setPropertyValue("XML", origineelXML)
 
// increase counter
teller = teller.toInteger() + 1
testRunner.testCase.testSuite.project.setPropertyValue("teller", teller.toString())

The SOAP Request

Now we have a variable on project level which stores the complete list of documents, which we can just use as normal in the request like this:

  <soap:Body>
      <ns1:Request>
         <Documents>${#Project#XML}</Documents>
      </ns1:Request>
   </soap:Body>
Advertisements
 
Leave a comment

Posted by on 21-03-2018 in Uncategorized

 

Tags: ,

Receive empty SOAP response in Oracle Service Bus (invalid SOAP fault)

We had some problems using Oracle Service Bus to perform a callout to an external webservice. All callouts resulted in a general BEA-38001 Error. In the end we discovered that the issue was functional (wrong data in the request), however the technical documentation of the external webservice informed us that we should receive a SOAP Fault. However this apparantly was not the case, as could be seen in the debug console. The SOAP Body element was empty:


After enabling message tracing on the specific business service we noticed the following logging:


<BEA-398203> <
 [OSB Tracing] Outbound response was received.

Service Ref = someProject/BusinessServices/someBusinessService
 URI = https://externalhost:443/SomePort
 Error code = BEA-380001
 Error Message = Internal Server Error
 Message ID = 8592423476474314819--7dc5b3e6.138425ff239.-29c0
 Response metadata =
 <xml-fragment>
 <tran:headers xsi:type="http:HttpResponseHeaders" xmlns:http="http://www.bea.com/wli/sb/transports/http" xmlns:tran="http://www.bea.com/wli/sb/transports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <tran:user-header name="SOAPAction" value="&quot;&quot;"/>
 <http:Connection>close</http:Connection>
 <http:Content-Length>787</http:Content-Length>
 <http:Content-Type>text/xml; charset=utf-8</http:Content-Type>
 <http:Date>Thu, 28 Jun 2012 11:25:22 GMT</http:Date>
 </tran:headers>
 <tran:response-code xmlns:tran="http://www.bea.com/wli/sb/transports">2</tran:response-code>
 <tran:response-message xmlns:tran="http://www.bea.com/wli/sb/transports">Internal Server Error</tran:response-message>
 <tran:encoding xmlns:tran="http://www.bea.com/wli/sb/transports">utf-8</tran:encoding>
 <http:http-response-code xmlns:http="http://www.bea.com/wli/sb/transports/http">500</http:http-response-code>
 </xml-fragment>
 Payload =
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><env:Body><env:Fault><faultcode xmlns="">env:003</faultcode><faultstring xmlns="">Standard Error: Authentication failed</faultstring><faultactor xmlns="">m86b1b2f-4d34-46cd-d538-c21ddb88743</faultactor></env:Fault></env:Body></env:Envelope>
>

Which is strange, because the payload clearly showed us that their is a soap envelope containing a soap fault. Normal OSB behaviour would mean this payload is then used in the <body> element of the SOAP response. However for some reason in this case the result was an empty <body> element, so looking more closely to the payload we could see that the content is:


<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <env:Body>
 <env:Fault>
 <faultcode xmlns="">env:003</faultcode>
 <faultstring xmlns="">Some Functional Error</faultstring>
 <faultactor xmlns=""someURI</faultactor>
 </env:Fault>
 </env:Body>
</env:Envelope>

The problem here seems to be the faultcode element, since it holds the value 003. However the W3C SOAP standard only allows the values: Client, Server, MustUnderstand and VersionMismatch. And it seems the  Oracle Service Bus is very strict about this.

After some additional testing with SOAPui as service consumer we can see that the message also fails there. Remember that SOAPui by default does not perform these validations and you will need Assertions for that.

This test (using a mockservice) shows that when the same response comes back with a valid faultcode the SOAPui assertions succeed. In the example we use the “.” seperator which is allowed and use Client as prefix since this is a valid faultcode.

The OSB is strict regarding the W3C standards and therefor elements like <body> are protected. (This is also why you shouldn’t use the Assign action on the $body variable, but better use the Replace node content functionality). So the real reason of the problem seems that the external service sends an invalid SOAP envelope.

Conclusion:

In the past I had an identical problem with an endpoint that returned a HTML page (with some functional text information) instead of an expected SOAP message. Lessons learned: if you really want to know what you response looks like, enable tracing on the Business Service and examine the payload.

 
5 Comments

Posted by on 10-08-2012 in Oracle, OSB, SOAP, SOAPui

 

Tags: , ,