Wednesday, October 16, 2013

SOAP UI Dynamic mock service using Groovy Script


SOAP UI Dynamic mock service using Groovy Script

Create dynamic mock service using SOAP UI . You will just need the WSDL . You should be familiar using the soap ui and creating the mock service . Following is to only make it dynamic
  1. Create a SoapUI project using the WSDL . Right click and select the mock service .
  2. Select the  WebService Method and Open the Response that has to be customized
  3. Create two files for Success and Error response and place them in folder  {Project-Path}/responses
  4. WebService Response ( Right portion of the Soap UI Window )will be made dynamic based on request.  Delete everything from mock response and  replace with${content} .  This value will be dynamically rendered from  groovy script
  5. Choose Dispatch -> Script , and then choose Dynamic Reponse
  6. Use the groovy script below , to render Success and Error Responses .

It works in the following way ,

  • if quotenumber is 9999  - send Error response
  • anything else - send Success Response


Now you can create more test cases and test them by changing the input in the xml . Providing  the input , output and the script below


Input ( for ref )

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="http://www.testing.com/WS/quoteWS">

  <soapenv:Header/>

  <soapenv:Body>

     <test:Quote>

        <QuoteRequest>

           <quoteNumber>9999</quoteNumber>

           <quoteTitle>?</quoteTitle>

           <quotePrice>?</quotePrice>

        </QuoteRequest>

     </test:Quote>

  </soapenv:Body>

</soapenv:Envelope>'



Output

Success
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="http://www.testing.com/WS/quoteWS">

  <soapenv:Header/>

  <soapenv:Body>

     <test:QuoteResponse>

        <QuoteReply>

           <status>Success</status>

           <!--Optional:-->

           <errorCode>0</errorCode>

           <!--Optional:-->

           <errorMessage></errorMessage>

           <!--Optional:-->

           <errorDetail></errorDetail>

        </QuoteReply>

     </test:QuoteResponse>

  </soapenv:Body>

</soapenv:Envelope>



Error

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="http://www.testing.com/WS/quoteWS">

  <soapenv:Header/>

  <soapenv:Body>

     <test:QuoteResponse>

        <QuoteReply>

           <status>ERROR</status>

           <!--Optional:-->

           <errorCode>11</errorCode>

           <!--Optional:-->

           <errorMessage>Failed</errorMessage>

           <!--Optional:-->

           <errorDetail>Something failed </errorDetail>

        </QuoteReply>

     </test:QuoteResponse>

  </soapenv:Body>

</soapenv:Envelope>


Groovy Script
import com.eviware.soapui.support.GroovyUtils

import groovy.xml.XmlUtil

log.info 'start'

def groovyUtils = new GroovyUtils(context)

def xmlParser = new XmlParser()

def responseContent

def requestXmlHolder = groovyUtils.getXmlHolder(mockRequest.getRequestContent())

requestXmlHolder.declareNamespace("test","http://www.testing.com/WS/quoteWS")

def quoteNumber = requestXmlHolder.getNodeValue("//test:Quote/QuoteRequest[1]/quoteNumber[1]")

log.info  quoteNumber



if(quoteNumber == '9999')

{

responseContent = xmlParser.parse(groovyUtils.projectPath +"/responses/error-response.xml")


}

else

{

responseContent = xmlParser.parse(groovyUtils.projectPath +"/responses/success-response.xml")

}

context.content = XmlUtil.serialize(responseContent)

log.info 'complete'

Wednesday, October 9, 2013

Spring Webservice using WebServiceTemplate


WebServiceTemplate

Here is the bean
 <bean id="wsTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
                <property name="defaultUri" value="http://localhost:8080/quote_test"/>
                <property name="marshaller" ref="QuoteRequestJAXBMarshaller"/>                 
                <property name="unmarshaller" ref="QuoteResponseJAXBMarshaller"/>
        </bean> 

You will need Marshaller and Unmarshaller , its part of oxm
include these in the header
  xmlns:oxm = "http://www.springframework.org/schema/oxm"

setup the marshaller and unmarshaller

  
<oxm:jaxb2-marshaller id = "QuoteRequestJAXBMarshaller">
    <oxm:class-to-be-bound name = "com.quote.services.model.Quote"/>
  </oxm:jaxb2-marshaller>  
  
  <oxm:jaxb2-marshaller id = "QuoteResponseJAXBMarshaller">
    <oxm:class-to-be-bound name = "com.quote.services.model.QuoteResponse"/>
  </oxm:jaxb2-marshaller>  
Marshaller and a UnMarshaller can be generated by xjc utility on schema (or) wsimport on WSDL. If you don't have the schema , it can be generated by the xml using many tools like http://www.freeformatter.com/  Here is example of xjc using ant
 
  <?xml version = "1.0" encoding = "UTF-8"?>

<project name = "mywsproject" 
        default = "generate">
 <property file = "build.properties"/>
 
  <fileset id = "tools" 
           dir = "tools">
    <include name = "**/*.jar"/>
  </fileset> 
 
 <taskdef name = "xjc" classname = "com.sun.tools.xjc.XJCTask">
   <classpath>
     <fileset refid = "tools"/>
   </classpath>
 </taskdef>
 
 <target name = "generate">
  <xjc schema = "src/main/xml/quote.xsd" 
      destdir = "src/main/java" 
      package = "com.quote.services.model"/>
 </target> 
</project>


 WSDL will have the schema and "wsimport" utility will generate the Classes for Marshaling and Un-Marshaling ( details of the wsimport utility can be found here http://ajaxrocks.blogspot.com/2013/08/jax-ws-call-ws-using-maven.html) ,after generation delete the  webservice and webservice port type classes .

No matter which way you use for generating the classes , you have to review and look for  JAXBElement. Basically if jaxb-api can't find the type of the element , it will generate as JAXBElement , so your response  instead of a "QuoteResponse" will be JAXBElement< QuoteResponse > . It can be fixed by commenting the create method in the ObjectFactory class

 
//   @XmlElementDecl(namespace = "http://www.test.com/WS/QuoteWS", name = "QuoteResponse")
//   public JAXBElement<QuoteResponse> createQuoteResponse(QuoteResponse value) {
//       return new JAXBElement<QuoteResponse>( , QuoteResponse.class, null, value);
//   
}

This also can happen with the attributes . Example below "errorMessage" is string but not defined correctly in the schema  so it become a JAXBElement . Comment these out and create them as String , generate getters and Setters
 

//   @XmlElementRef(name = "errorMessage", type = JAXBElement.class)
//    protected JAXBElement<String> errorMessage;

Calling from Java Service , is now easy as calling a method and getting a response
@Service("myQuoteService")
public class QuoteServiceImpl {
    @Autowired
    private WebServiceOperations wsTemplate;
    
    
    public QuoteResponse generateQuote()
    {
     Quote quote = new Quote();
     quote.setPrice("99.99");
     quote.setAmount("100");
     
     QuoteRequest quoterequest = new QuoteRequest();
     quoterequest.setQuote(quote);
     
     return  (QuoteResponse)wsTemplate.marshalSendAndReceive(quoterequest);
     
    }
}



Tuesday, October 8, 2013

Spring Webservice using JAXWS and JaxWsPortProxyFactoryBean

Calling WebService using JaxWsPortProxyFactoryBean


This is probably the easiest way to call the webservice . Generate the necessary classes for the webservice by using the "wsimport" utility ( have a look at http://ajaxrocks.blogspot.com/2013/08/jax-ws-call-ws-using-maven.html) . Then you can configure the bean to use the generated classes as shown
 
<bean  id="myWebservice" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
<property name="serviceInterface" value="com.myws.proxy.MyTestWebService" />
<property name="wsdlDocumentUrl" value="wsdl/mytest-service.wsdl" />
<property name="namespaceUri" value="http://mycompany.com/myservice" />
<property name="serviceName" value="MyTestService" />
<property name="endpointAddress" value="http://www.test.com/webservices/mytest-service?wsdl" />
<property name="username" value="username"/>
<property name="password" value="password"/>
</bean>
Use username and password if required otherwise it can be removed . Just wire this bean to your class and call the webservice

JaxWsPortProxyFactoryBean is part of spring-web utility ,You have to include the following in your pom.xml

   <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>