Friday, January 27, 2012

SOAP message correlation with JMeter Beanshell pre-processor

When testing service oriented solutions, it is often required to correlate SOAP or POX messages with each other. For example, first you may need to talk to one particular web service and get the response back. Then you will need to extract some properties from the response and include them in subsequent requests. In these situations, you cannot just send the SOAP messages to the web service. In other words, you should do some preprocessing before doing the second service call.

Apache Jmeter provides you with Pre-Processor elements to handle these types of requirements. In this post, we will look into one of the useful pre-processor element, Bean Shell PreProcessor

We will do a simple echo web service call first and extract the response value to a user defined variable. Then, we will use Bean Shell PreProcessor to modify the second SOAP request.

Step 1
Start Jmeter and create a new test plan. Add two SOAP/XML-RPC request samplers. Add the following request for one sampler. Name the sampler as "echoStringRequest"

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.carbon.wso2.org">
<soapenv:Body>
<ser:echoString>
<ser:s>MSFT</ser:s>
</ser:echoString>
</soapenv:Body>
</soapenv:Envelope>

For the second SOAP/XML-RPC request sampler, add the following request. Name it as "StockQuoteRequest"

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<p:getQuote xmlns:p="http://services.samples/xsd">
<p:request>
<p:symbol>&lt/p:symbol>
</p:request>
</p:getQuote>
</s:Body>
</s:Envelope>

Note that there is no relationship between these two web service calls. I use these just for the demonstration purposes only.

Step 2:

The above two requests will be sent to two web services hosted in Apache Axis2 (or WSO2 Application Server). Therefore, download Axis2Service.aar and SimpleStockQuoteService.aar deploy the services.

Step 3:

Now, Send the above echoStringRequest to Axis2Service and check the response. You will see something like below.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:echoStringResponse xmlns:ns="http://service.carbon.wso2.org"><ns:return>MSFT</ns:return>
</ns:echoStringResponse>
</soapenv:Body>
</soapenv:Envelope>


We are going to extract the value of <echoStringResponse> element and assign it to a variable so that we can use the value later. For that, we need to add the User Defined Variables config element to the thread group. Right click on thread group and select Add --> Config Elements ---> User Defined Variables

Name: echoResponse
Value: empty



Step 4:

We need to extract the echoStringResponse from the above SOAP response. For that, we will use XPAth extractor post-processor element.

Right click on the echoStringRequest SOAP/XML-RPC sampler and add XPath Extractor.



Specify "//echoStringResponse/return" as the Xpath query and "echoResponse" (the user defined variable) as the reference name.

Step 5

In the previous two steps, we extracted echoStringResponse value from the SOAP response message and assign it to a user defined variable. Now, we need to insert the extracted string into the second SOAP request.
As I mentioned at the beginning, we use BeanShell preprocessor to modify the SOAP request before submission.

BeanShell is a simple scripting language which dynamically executes standard java syntax.

Lets add the beanshell preprocessor as a child of our second SOAP sampler, StockQuoteRequest.
Right click on StockQuoteRequest SOAP/XML-RPC sampler and select Add --> Pre Processors --> BeanShell Pre Processor

You can include the processing script inside script pane. Here, first we read the StockQuoteRequest to a String and replace the <symbol> element with the echoResponse value which has been placed under the user defined variable.

import org.apache.jmeter.protocol.http.sampler.SoapSampler;
SoapSampler soapSampler = (SoapSampler) sampler;
String stockRequest = soapSampler.getXmlData().replaceFirst("#symbol#", vars.get("echoResponse"));
soapSampler.setXmlData(stockRequest);
SoapSampler class can be used to manipulate a lot of operations of SOAP/XML-RPC request such as read XML data, modify data and set SOAPAction etc..

Here, sampler is a variable provided by jmeter which refers to the parent SOAP request.



Step 6

We have completed adding all the necessary elements to our Jmeter test plan. Now, add a listener to visualize the results and run the test.

You will see that the response of the echoStringRequest will be used for the StockQuoteRequest by extracting the echoStringResponse value from the first request.

2 comments:

Stefano Gregori said...

You can also obtain the same effect by adding a BeanShell as a post processor just after extracting the desired value from the response so that you do not need to manipulate the Sampler output but just to use the elaborated value from user defined variables.
IMHO it looks more clean and simple.

Rodney Barbati said...

I am amazed you actually got the XPath Extractor to work - I have never been able to use it.

Anyway, I use the Regular Expression Extractor which outputs directly to vars as is, then use the variable in the request of the second service call like ${variable_name_g1} - the g1 is due to the processing of the reg_exp (in this case it means the first match).