/JMeterSoapPlugin

The plugin provides a similar interface as the built in WebService(SOAP) Request. It can handle Digest Authentication as well.

Primary LanguageJava

Implementing a Soap Plugin for Apache JMeter
============================================

JMeter already has a WebService(SOAP) Request which works fine. Unfortunately it can not handle authentication. This is why I had to write this plugin. The plugin uses a interface very similar to WebService(SOAP) Request. My hope is that later JMeter will adopt the authentication feature to JMeter core.

Plugin Installation
-------------------

The installation is quite simple just download jmetersoapplugin.jar and put it in $JMETER_HOME/lib/ext. Once you restart JMeter you should see a new option under Add -> Samplers called "Enhanced JDBC Request". It works just like the standard WebService(SOAP) Request.
You will also need the spring-ws client libraries.

Additional libs for JMeter in lib/ext:
o spring-ws-2.1.0.RELEASE-all
o springframework.*-3.1.0.RELEASE
o wss4j-1.6.6.jar
o xmlsec-1.5.2.jar


Implementing a simple Soap webservice
=====================================

This section describes how I created a simple webservice. I started from this excellent tutorial:
http://blog.espenberntsen.net/2010/02/26/generate-jaxb-classes-from-an-xsd-schema-and-the-schema-from-an-xml-sample-document/

Generating an XSD schema from a sample XML document 
---------------------------------------------------

Here a sample XML file for a start:

<addRequest>
  <a>10</a>
  <b>20</b>
</addRequest>

The XSD schema is generated from the sample XML using the Trang project which lives here: http://code.google.com/p/jing-trang/

build -f build-generate-schema.xml

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="addRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" ref="value"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="value" type="xs:integer"/>
</xs:schema>

The XSD needs some tweaking (here the finalized version):

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.testing-software.org/calc" xmlns:o="http://www.testing-software.org/calc">

  <xs:element name="addRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="a" type="xs:integer" />
        <xs:element name="b" type="xs:integer" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="addResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="result" type="xs:integer" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>


Generating class files from XSD using JAXB
------------------------------------------

From Java 1.6 on JAXB is included! So nothing to install/download here. JAXB will generate some class files in the src/org/testingsoftware/org/generated folder:

ant -f build-generate-jaxb.xml


Where is the WSDL?
------------------

You don’t need to create a WSDL file with Spring WS. WSDL4J does create the WSDL dynamically for you.


Building the war file
---------------------

To build just run maven:

mvn package


Running demo_server using Tomcat
--------------------------------

Start Tomcat using maven: 
mvn tomcat:run

Now you can access the new service:
http://localhost:8080/demo_server/calc-service/calcServiceDefinition.wsdl


Playing with the demo_server
----------------------------

In case you do not provide valid parameters, you get a nice SoapFault:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
         <faultcode>SOAP-ENV:Client</faultcode>
         <faultstring xml:lang="en">Validation error</faultstring>
         <detail>
            <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-datatype-valid.1.2.1: 'xy' is not a valid value for 'integer'.</spring-ws:ValidationError>
            <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: The value 'xy' of element 'calc:a' is not valid.</spring-ws:ValidationError>
         </detail>
      </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Once you provide valid input like the following:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:calc="http://www.testing-software.org/calc">
   <soapenv:Header/>
   <soapenv:Body>
      <calc:addRequest>
         <calc:a>10</calc:a>
         <calc:b>20</calc:b>
      </calc:addRequest>
   </soapenv:Body>
</soapenv:Envelope>

You can do that for example using curl (on the command line):
curl -X POST -H 'Content-type: text/xml' --data @soap_request.xml http://localhost:8080/demo_server/calc-service

...the CalcService does a nice job:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <ns2:addResponse xmlns:ns2="http://www.testing-software.org/calc">
         <ns2:result>30</ns2:result>
      </ns2:addResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Now the demo_server is ready to be used.


Implementing a simple Soap webservice test (client)
===================================================

This section describes how I created a simple webservice test. The test runs against a real webservice (see above). I started from this excellent tutorial:
http://blog.espenberntsen.net/2010/02/28/spring-ws-client/

The junit testcase looks like the following (all in src/test/...):

public class CalcServiceTest {

  @Autowired
  @Qualifier("webServiceTemplate")
  private WebServiceTemplate webServiceTemplate;

  @Test
  public void testCalcService() {

    AddRequest request = new ObjectFactory().createAddRequest();
    request.setA(BigInteger.valueOf(10));
    request.setB(BigInteger.valueOf(20));
    AddResponse response = (AddResponse) webServiceTemplate
        .marshalSendAndReceive(request);

    assertEquals(BigInteger.valueOf(30), response.getResult());
  }
  (... more tests here)

The test needs wiring information in test-config.xml:

  <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">

    <property name="marshaller" ref="marshaller" />
    <property name="unmarshaller" ref="marshaller" />
    <property name="defaultUri"
      value="http://localhost:8080/demo_server/calc-service" />
  </bean>

Now you can run the test (make sure the server is started).