2007/09/06
6 Sep, 2007

Web Services Versioning using WSO2 WSAS and WSO2 ESB

  • Davanum Srinivas
  • - WSO2

Let us review what we know already. Axis 1.x based Web services are
primarily of rpc/encoded style, as that was the default option. Axis2 used
document/literal style as the default. So the SOAP requests that are sent by
the two sets of clients are very different from each other. So the first
issue is to figure out how to re-use the Axis 1.x classes and the wsdd
descriptor (migration). The second issue is how we can support legacy
(rpc/encoded) and modern (doc/lit) clients at the same time (versioning).
Thankfully, WSO2 WSAS and WSO2 ESB make it easy both for migration and for
versioning.

Sample Service and Deployment Descriptors

Let us take a quick look at the sample service and classes that we will
work with in this article. MyService is the service that needs to be
deployed:

package org.wso2.samples;

public class MyService {
        public Employee[] getEmployees(){
                return new Employee[]{
                        new Employee("Sanjiva","Weerawarana",1),
                        new Employee("Paul","Fremantle",2)
                };
        }
}

and here's the Employee class:

package org.wso2.samples;

public class Employee {
    public String firstName = null;
    public String lastName = null;
    public int id = 0;
    public Employee() {
    }
    public Employee(String firstName, String lastName, int id){
                this.firstName = firstName;
                this.lastName = lastName;
                this.id = id;
    }
        public String getFirstName() {
                return firstName;
        }
        public void setFirstName(String firstName) {
                this.firstName = firstName;
        }
        public String getLastName() {
                return lastName;
        }
        public void setLastName(String lastName) {
                this.lastName = lastName;
        }
        public int getID() {
                return id;
        }
        public void setID(int id) {
                this.id = id;
        }
}

We can deploy this service in Axis 1.x using the following snippet in the
server-config.wsdd:

        <service name="MyOldService" provider="java:RPC" style="rpc" use="encoded">
                <parameter name="wsdlTargetNamespace" value="https://samples.wso2.org"/>
                <parameter name="wsdlServiceElement" value="MyServiceService"/>
                <parameter name="schemaUnqualified" value="https://samples.wso2.org"/>
                <parameter name="wsdlServicePort" value="MyService"/>
                <parameter name="className" value="org.wso2.samples.MyService"/>
                <parameter name="wsdlPortType" value="MyService"/>
                <parameter name="typeMappingVersion" value="1.2"/>
                <operation name="getEmployees" qname="operNS:getEmployees" xmlns:operNS="https://samples.wso2.org" 
                              returnQName="getEmployeesReturn" returnType="rtns:ArrayOfEmployee" 
                              xmlns:rtns="https://samples.wso2.org" returnItemType="tns2:Employee" 
                              xmlns:tns2="https://samples.wso2.org">
                </operation>
                <parameter name="allowedMethods" value="getEmployees"/>
                <typeMapping xmlns:ns="https://samples.wso2.org" qname="ns:Employee" type="java:org.wso2.samples.Employee" 
                        serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" 
                        deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" 
                        encodingStyle="https://schemas.xmlsoap.org/soap/encoding/"/>
                <arrayMapping xmlns:ns="https://samples.wso2.org" qname="ns:ArrayOfEmployee" 
                        type="java:org.wso2.samples.Employee[]" innerType="cmp-ns:Employee" 
                        xmlns:cmp-ns="https://samples.wso2.org" 
                        encodingStyle="https://schemas.xmlsoap.org/soap/encoding/"/>
        </service>

And the following services.xml in Axis2:

<service name="MyService">
        <description>
                My Service class deployed on Axis2
        </description>
        <parameter name="ServiceClass">org.wso2.samples.MyService</parameter>
        <operation name="getEmployees">
                <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
        </operation>
</service>

Installing Services on WSO2 WSAS

  • Download WSO2 WSAS 2.0 from href="https://dist.wso2.org/products/wsas/java/2.0/">https://dist.wso2.org/products/wsas/java/2.0/
    and unzip to say C:\wso2wsas-2.0
  • The WSO2 WSAS server by default uses ports 9762 and 9443. Unfortunately
    WSO2 ESB uses 8080, 8443 and 9443. So let's switch the WSAS ports to
    avoid clashing with ESB
  • Edit c:\wso2wsas-2.0\conf\server.xml and add the following snippet:
        <Ports>
            <HTTP>7070</HTTP>
            <HTTPS>7443</HTTPS>
        </Ports>
  • Edit c:\wso2wsas-2.0\conf\axis2.xml and replace the ports (9762 with
    7070 and 9443 with 7443)
  • Make sure JDK1.5's java.exe is on the command line, cd to
    c:\wso2wsas-2.0\bin and run "wso2wsas run". You will see an output
    similar to the one below:
    Starting WSO2 Web Services Application Server v2.0 (in JDK 1.5)
     Using WSO2WSAS_HOME:   C:\WSO2WS~1.0\bin\..
     Using JAVA_HOME:       C:\JDK15
     INFO [2007-09-05 23:23:27,552]  Using WSO2 WSAS Home = C:\WSO2WS~1.0\bin\..
     INFO [2007-09-05 23:23:27,585]  Using Server Info Class = org.wso2.wsas.serverinfo.EmbeddedTomcatServerInfo
     INFO [2007-09-05 23:23:33,321]  Deploying module: addressing-1.25
     INFO [2007-09-05 23:23:33,374]  Deploying module: rahas-1.25
     INFO [2007-09-05 23:23:33,641]  Deploying module: rampart-1.25
     INFO [2007-09-05 23:23:33,666]  Deploying module: wso2mex-2.0
     INFO [2007-09-05 23:23:34,068]  Deploying module: sandesha2-2.0
     INFO [2007-09-05 23:23:34,085]  Deploying module: wso2statistics-2.0
     INFO [2007-09-05 23:23:34,126]  Deploying module: wso2throttle-2.0
     INFO [2007-09-05 23:23:34,148]  Deploying module: wso2tracer-2.0
     INFO [2007-09-05 23:23:34,152]  Deploying module: wso2wsas-admin-2.0
     INFO [2007-09-05 23:23:34,174]  Deploying module: wso2xfer-2.0
     INFO [2007-09-05 23:23:34,527]  Deploying module: addressing-1.25
     INFO [2007-09-05 23:23:34,540]  Deploying module: wso2mex-2.0
     INFO [2007-09-05 23:23:43,484]  Deploying Web service: echo.aar
     INFO [2007-09-05 23:23:44,122]  Deploying Web service: version.aar
     INFO [2007-09-05 23:23:44,241]  Deploying Web service: wso2codegen.aar
     INFO [2007-09-05 23:23:44,580]  Deploying Web service: wso2wsas-administration.aar
     INFO [2007-09-05 23:23:44,865]  Deploying Web service: wso2wsas-sts.aar
     INFO [2007-09-05 23:23:45,128]  Deploying Web service: xkms.aar
     INFO [2007-09-05 23:23:46,719]  Command listener starting on port ----> 6666
     INFO [2007-09-05 23:23:46,719]  Using Repository C:\WSO2WS~1.0\bin\../repository/
     INFO [2007-09-05 23:23:46,720]
     INFO [2007-09-05 23:23:46,720]  Listening for HTTP on             ----> 7070
     INFO [2007-09-05 23:23:46,720]  Listening for HTTPS on            ----> 7443
     INFO [2007-09-05 23:23:46,720]
     INFO [2007-09-05 23:23:46,720]  WSO2 WSAS started in 22131 ms
    
        
  • Point your browser to https://localhost:7443/ Login using admin/admin
    as the user ID and password and click on the services link.
  • To upload the Axis2 service, click on "Upload Service Artifact
    (.aar,.jar,.zip,.dbs)" and upload myservice-axis2.aar (see Downloads
    below)
  • To upload the Axis1 service, click on "Upload Axis1 Service (.wsdd)"
    and upload myservice-axis1.jar and server-config.wsdd (see Downloads
    below)
  • After a few seconds, you will see both the Axis1 and Axis2 services
    show up on the console:

Install WSO2 ESB and Set up a Mediation for Versioning

  • Download WSO2 ESB 1.0 from href="https://dist.wso2.org/products/esb/java/1.0/">https://dist.wso2.org/products/esb/java/1.0/
    and unzip to say C:\wso2esb-1.0
  • Make sure JDK1.5's java.exe is on the command line, cd to
    c:\wso2esb-1.0\bin and run "wso2-esb run". You will see an output similar
    to the one below:
     Using Bouncy castle JAR for Java 1.5
    "Starting WSO2 Enterprise Service Bus ..."
    Using ESB_HOME:        E:\WSO2ES~1.0\bin\..
    Using JAVA_HOME:       C:\JDK15
    Using SYNAPSE_XML:     -Dsynapse.xml="E:\WSO2ES~1.0\bin\..\conf\synapse.xml"
     INFO [06 Sep 00:38:40]  ServiceBusConfiguration - Service Bus Configuration loaded from : conf/server.xml
     INFO [06 Sep 00:38:40]  ServiceBus - Using Repository E:\WSO2ES~1.0\.\repository
     INFO [06 Sep 00:38:41]  ServiceBusManager - Database server started on localhost over port 1528
     INFO [06 Sep 00:38:42]  ModuleDeployer - Deploying module: addressing
     INFO [06 Sep 00:38:42]  ModuleDeployer - Deploying module: authentication
     INFO [06 Sep 00:38:42]  ModuleDeployer - Deploying module: rampart
     INFO [06 Sep 00:38:42]  ModuleDeployer - Deploying module: sandesha2
     INFO [06 Sep 00:38:42]  ModuleDeployer - Deploying module: synapse-1.0
     INFO [06 Sep 00:38:42]  ModuleDeployer - Deploying module: wso2statistics
     INFO [06 Sep 00:38:42]  SynapseModule - Initializing the Synapse configuration ...
     INFO [06 Sep 00:38:42]  XMLConfigurationBuilder - Generating the Synapse configuration model by parsing the XML configuration
     INFO [06 Sep 00:38:42]  SynapseConfigurationBuilder - Loaded Synapse configuration from : E:\WSO2ES~1.0\bin\..\conf\synapse.xml
     INFO [06 Sep 00:38:42]  SynapseModule - Deploying the Synapse service..
     INFO [06 Sep 00:38:42]  SynapseModule - Initializing Sandesha 2...
     INFO [06 Sep 00:38:42]  SynapseModule - Deploying Proxy services...
     INFO [06 Sep 00:38:42]  SynapseModule - Synapse initialized successfully...!
     INFO [06 Sep 00:38:43]  HttpCoreNIOSender - HTTPS Sender starting
     INFO [06 Sep 00:38:43]  HttpCoreNIOSender - HTTP Sender starting
     INFO [06 Sep 00:38:53]  ServiceDeployer - Deploying Web service: ESBAdmin.aar
     INFO [06 Sep 00:38:54]  HttpCoreNIOListener - HTTPS Listener starting on port : 8443
     INFO [06 Sep 00:38:54]  HttpCoreNIOListener - HTTP Listener starting on port : 8080
     INFO [06 Sep 00:38:54]  JettyServer - Console listener started on port 9443 over HTTPS. Connect to https://192.168.2.105:9443/
     INFO [06 Sep 00:38:54]  ServiceBus - WSO2 ESB started in 15004 ms
    
        
  • Point your browser to https://localhost:9443/ Login using admin/admin
    as the user ID and password, and click on the Configuration link
  • Copy the contents of esb-configuration.xml into the edit box, click
    Update and then click Save.
  • Now if you click on Proxy Services, Endpoints or Sequences, you can
    grapically view the information that was picked up from the
    esb-configuration.xml
  • In particular, https://localhost:8080/soap/MyService is the new endpoint
    that redirects the SOAP requests to
    https://localhost:7070/services/MyService for newer doc/lit clients and to
    https://localhost:7070/services/MyOldService for old rpc/encoded style
    clients.
  • When you click on Sequences, and look at "inSequence", you will see
    that we use an xpath expression //*[local-name()='getEmployees']
    to decide which endpoint needs to be invoked. Here's the corresponding
    configuration snippet:
            <syn:sequence name="inSequence">
                    <syn:filter xpath="//*[local-name()='getEmployees']">
                            <syn:send>
                                    <syn:endpoint key="Axis1Service"/>
                            </syn:send>
                            <syn:drop/>
                    </syn:filter>
                    <syn:send>
                            <syn:endpoint key="Axis2Service"/>
                    </syn:send>
            </syn:sequence>
    
        

    Basically inside the SOAP body, for rpc/encoded requests, there is an
    additional element named "getEmployees". So we look for that to identify
    that it is an rpc/encoded request.

  • If you browse through the esb-configuration.xml, you will see that we
    used an inline WSDL for the axis1 service and a URL for the axis2
    service. This is because, when we deploy an Axis1 service, the WSDL picks
    up the https:// endpoint. So we had to copy the WSDL and make the change
    to refer to https:// endpoint.

Testing the New Endpoint

  • You can use a tool like SOAPUI or XMLSPY to test the actual Web
    services deployed on WSO2 WSAS first, the wsdl's for those are
    https://localhost:7070/services/MyOldService?wsdl and
    https://localhost:7070/services/MyService?wsdl
  • For example, when you send the following SOAP request to
    https://localhost:7070/services/MyOldService
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="https://schemas.xmlsoap.org/soap/envelope/" 
    	xmlns:SOAP-ENC="https://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="https://www.w3.org/2001/XMLSchema">
            <SOAP-ENV:Body>
                    <m:getEmployees xmlns:m="https://samples.wso2.org" SOAP-ENV:encodingStyle="https://schemas.xmlsoap.org/soap/encoding/"/>
            </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    
        

    you will get the following:

    <soapenv:Envelope xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/" 
    	          xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="https://www.w3.org/2001/XMLSchema">
            <soapenv:Body xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/">
                    <ns1:getEmployeesResponse xmlns:ns1="https://samples.wso2.org" 
    				soapenv:encodingStyle="https://schemas.xmlsoap.org/soap/encoding/">
                            <getEmployeesReturn xmlns:soapenc="https://schemas.xmlsoap.org/soap/encoding/" 
    						soapenc:arrayType="ns1:Employee[2]" xsi:type="soapenc:Array">
                                    <getEmployeesReturn href="#id0"/>
                                    <getEmployeesReturn href="#id1"/>
                            </getEmployeesReturn>
                    </ns1:getEmployeesResponse>
                    <multiRef xmlns:soapenc="https://schemas.xmlsoap.org/soap/encoding/" 
    				xmlns:ns2="https://samples.wso2.org" id="id0" soapenc:root="0" 
    				soapenv:encodingStyle="https://schemas.xmlsoap.org/soap/encoding/" 
    				xsi:type="ns2:Employee">
                            <ID xsi:type="xsd:int">1</ID>
                            <firstName xsi:type="xsd:string">Sanjiva</firstName>
                            <lastName xsi:type="xsd:string">Weerawarana</lastName>
                            <id xsi:type="xsd:int">1</id>
                    </multiRef>
                    <multiRef xmlns:ns3="https://samples.wso2.org" xmlns:soapenc="https://schemas.xmlsoap.org/soap/encoding/" 
    				id="id1" soapenc:root="0" soapenv:encodingStyle="https://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns3:Employee">
                            <ID xsi:type="xsd:int">2</ID>
                            <firstName xsi:type="xsd:string">Paul</firstName>
                            <lastName xsi:type="xsd:string">Fremantle</lastName>
                            <id xsi:type="xsd:int">2</id>
                    </multiRef>
            </soapenv:Body>
    </soapenv:Envelope>
    
        
  • For example, when you send the following SOAP request to
    https://localhost:7070/services/MyService
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="https://schemas.xmlsoap.org/soap/envelope/" 
    	xmlns:SOAP-ENC="https://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" 
    	xmlns:xsd="https://www.w3.org/2001/XMLSchema">
            <SOAP-ENV:Body/>
    </SOAP-ENV:Envelope>
    
        

    you will get the following:

    <soapenv:Envelope xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Body>
                    <ns:getEmployeesResponse xmlns:ns="https://samples.wso2.org" xmlns:ax225="https://samples.wso2.org/xsd">
                            <ns:return type="org.wso2.samples.Employee">
                                    <ax225:firstName>Sanjiva</ax225:firstName>
                                    <ax225:lastName>Weerawarana</ax225:lastName>
                            </ns:return>
                            <ns:return type="org.wso2.samples.Employee">
                                    <ax225:firstName>Paul</ax225:firstName>
                                    <ax225:lastName>Fremantle</ax225:lastName>
                            </ns:return>
                    </ns:getEmployeesResponse>
            </soapenv:Body>
    </soapenv:Envelope>
    
        
  • Finally, try sending both types of SOAP requests to
    https://localhost:8080/soap/MyService and make sure you get the right
    response back.

Applies To

1. WSO2 WSAS 2.0

2. WSO2 ESB 1.0

 

Downloads

1. myservice-axis1.jar and server-config.wsdd for deploying the
MyOldService - Axis1 service

2. myservice-axis2.aar for
deploying MyService - Axis2 service

3. esb-configuration.xml -
pre-built ESB Configuration

 

About Author

  • Davanum Srinivas
  • WSO2 Inc.