Migrating from Axis 1.x to Axis 2

Compatibility

Axis1.x and Axis2 have been evolved from different architectures.

Speed - Axis2 is based on StAX API, which gives greater speed than SAX event base parsing that has been used in Axis1.x.

Stability - Axis2 has fixed phases and for extensions an area of user defined phases. This allows far more stability and flexibility than Axis1.x.

Transport framework - Simple abstraction designing of transports (i.e., senders and listeners for SOAP over various protocols such as SMTP, etc), allow far more flexibility and the core of the engine is completely transport-independent.

WSDL Support - Axis2 supports version 1.1 and 2.0, which allow creating stubs and skeletons, to manipulate web service arena.

Component - Oriented Architecture - This is merely through archives (.mar and .aar) . Easily reusable components such as Handlers, Modules allow patterns processing for your applications, or to distribute to partners. Axis2 more concern on the "Module" concept rather Handler concept. Modules contain handlers that have been ordered through phase rules. which being ordered to specific service(s).

Getting Started

Lets look at a simple example of echoing at client API

Axis 1.x

import ..
public class TestClient {
        public static void main(String [] args) {
                try {
                        String endpoint = ...
                        Service axisService = new Service();
                        Call call = (Call) axisService.createCall();
                        call.setTargetEndpointAddress( new java.net.URL(endpoint) );
                        call.setOperationName(new QName("http://soapinterop.org/", echoString"));
                        String ret = (String) call.invoke( new Object[] { "Hello!" } );
                        System.out.println("Sent 'Hello!', got '" + ret + "'");
                } catch (Exception e) {
                        System.err.println(e.toString());
                }
        }
}

Axis 2

import ....
public class EchoBlockingClient {
        private static EndpointReference targetEPR = new EndpointReference(
        AddressingConstants.WSA_TO,
                                "http://127.0.0.1:8080/axis2/services/MyService");
        public static void main(String[] args) {
                try {
                        OMElement payload = ClientUtil.getEchoOMElement();
                        Options options = new Options();
                        Call call = new Call();
                        options.setTo(targetEPR);
                        options.setSenderTransport(new TransportOutDescription(new QName(Constants.TRANSPORT_HTTP)));
                        //Blocking invocation
                        OMElement result = (OMElement) call.invokeBlocking("echo",payload);
                        ...
                } catch (AxisFault axisFault) {
                        axisFault.printStackTrace();
                } catch (XMLStreamException e) {
                        e.printStackTrace();
                }
        }
}

It has clearly depicted that the invocation in Axis2 is dealt with SOAP body element itself. Here the invocation is synchronous, and Axis2 can handle Asynchronous invocation as well. Above "payload" is the SOAP body element which should go in the Envelop.

Once the service is called through Stub in Axis2, "payload" is according to the data binding framework that will be using. So the extra work of "payload" will be vanished.

Apart from Synchronous invocation, Axis2 support Asynchronous invocation through invokeNonBlocking(). Synchronous/Asynchronous invocations can handle both single/double HTTP connection.

With the advance architecture Axis2 is capable of handling Megabytes of Requests and Responses, which is far form Axis1.x.

Custom Deployment of Services, Handlers and Modules

In Axis 1.x deployment of services is via WSDD, which is for my opinion highly cumbersome. Service deployment in Axis2 is straight forward and dynamic. Dynamic behavior is from the Administrator facility given by development in server side. It's just a matter of creating a .aar file, and deploying it ,which more detail is given in the Axis2 user guide.

Axis2 is far way from Handler concept and more into the Module concept, which is abstractly speaking, a collection of handlers with Rules of governing. Modules created as a .mar file. It has module.xml, which is the brain behind manipulating handlers.

When a service is called through a handler, it is just a matter of giving reference to the module that includes the handler in the services.xml. Apart from that a handler can be directly called to a particular service, via services.xml, no module is needed, and several handlers can be invoked when the handlers are registered with the proper phases.

Services are hot deployable in Axis2 and dynamic, but Modules. This is one feature, which is unique to Axis2.

Lets take a detailed look at what it takes to migrate Axis 1.x handlers to Axis 2 modules via the SOAP Monitor. The SOAP Monitor is really three components: An applet which displays responses / requests, a servlet which binds to a default port of 5001 and connects to the applet, and a handler chain used to intercept the soap messages. Here we'll focus on the handler.

Axis 1.x required two WSDD's to use the SOAP Monitor. First, the SOAP Monitor Handler itself:

<deployment xmlns="http://xml.apache.org/axis/wsdd/"
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
    
  <handler name="soapmonitor" 
      type="java:org.apache.axis.handlers.SOAPMonitorHandler">
    <parameter name="wsdlURL" 
      value="/wzs/SOAPMonitorService-impl.wsdl"/>
    <parameter name="namespace" 
      value="http://tempuri.org/wsdl/2001/12/SOAPMonitorService-impl.wsdl"/>
    <parameter name="serviceName" value="SOAPMonitorService"/>
    <parameter name="portName" value="Demo"/>
  </handler>

  <service name="SOAPMonitorService" provider="java:RPC">
    <parameter name="allowedMethods" value="publishMessage"/>
    <parameter name="className" 
      value="org.apache.axis.monitor.SOAPMonitorService"/>
    <parameter name="scope" value="Application"/>
  </service>
</deployment>

Axis 1.x requires a reference to the Handler in the user's WSDD that defines their Web Service:

<deployment name="example" xmlns="http://xml.apache.org/axis/wsdd/" 
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  
  <service name="urn:myService" provider="java:RPC">
    <parameter name="className" value="org.MyService"/>
    <parameter name="allowedMethods" value="*"/>

    <requestFlow>
      <handler type="soapmonitor"/>
    </requestFlow>
    <responseFlow>
      <handler type="soapmonitor"/>
    </responseFlow>

  </service>
</deployment>

Axis 2 requires a module.xml, placed inside a jar with a .mar extension under WEB-INF/modules, to define a Handler:

<module name="soapmonitor" class="org.apache.axis2.handlers.soapmonitor.SOAPMonitorModule">
    <inflow>
        <handler name="InFlowSOAPMonitorHandler" class="org.apache.axis2.handlers.soapmonitor.SOAPMonitorHandler">
            <order phase="soapmonitorPhase"/>
        </handler>
    </inflow>

    <outflow>
        <handler name="OutFlowSOAPMonitorHandler" class="org.apache.axis2.handlers.soapmonitor.SOAPMonitorHandler">
            <order phase="soapmonitorPhase"/>
        </handler>
    </outflow>

    <Outfaultflow>
        <handler name="FaultOutFlowSOAPMonitorHandler" class="org.apache.axis2.handlers.soapmonitor.SOAPMonitorHandler">
            <order phase="soapmonitorPhase"/>
        </handler>
    </Outfaultflow>

    <INfaultflow>
        <handler name="FaultInFlowSOAPMonitorHandler" class="org.apache.axis2.handlers.soapmonitor.SOAPMonitorHandler">
            <order phase="soapmonitorPhase"/>
        </handler>
    </INfaultflow>
</module>

The SOAPMonitorModule referenced above simply implements org.apache.axis2.modules.Module and is used for any additional tasks needed to initialize the module and shutdown the module. In this case nothing is needed and the implemented interface methods have blank bodies. Furthermore, the 'soapmonitorPhase' will be used later below in the axis2.xml .

Axis 1.x the SOAPMonitorHandler has the class signature as:

public class SOAPMonitorHandler extends BasicHandler

Axis 2 the SOAPMonitorHandler has the class signature as:

public class SOAPMonitorHandler extends AbstractHandler implements Handler

In axis2, you need to reference the module that contains the handler chain that you want to use inside your services.xml:

<service name="ExampleService">
    <module ref="soapmonitor"/>
    <description>
       This service has the SOAP Monitor wired in 
    </description>
    <parameter name="ServiceClass" locked="false">org.ExampleService</parameter>
    <operation name="myExecute">
        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
    </operation>
</service>

Finally, axis2 requires you to make some changes to axis2.xml. Start by adding a global module:

    <module ref="soapmonitor"/>

Then define your phase orders for 'soapmonitorPhase' referenced in the module.xml :

    <phaseOrder type="inflow">
        <!--  System pre defined phases       -->
        <phase name="TransportIn"/>
        <phase name="PreDispatch"/>
        <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase">
            <handler name="AddressingBasedDispatcher"
                     class="org.apache.axis2.engine.AddressingBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>

            <handler name="RequestURIBasedDispatcher"
                     class="org.apache.axis2.engine.RequestURIBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>

            <handler name="SOAPActionBasedDispatcher"
                     class="org.apache.axis2.engine.SOAPActionBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>

            <handler name="SOAPMessageBodyBasedDispatcher"
                     class="org.apache.axis2.engine.SOAPMessageBodyBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>
            <handler name="InstanceDispatcher"
                     class="org.apache.axis2.engine.InstanceDispatcher">
                <order phase="PostDispatch"/>
            </handler>
        </phase>
        <!--  System pre defined phases       -->
        <!--   After Postdispatch phase module author or or service author can add any phase he want      -->
        <phase name="userphase1"/>
        <phase name="soapmonitorPhase"/>
    </phaseOrder>
    <phaseOrder type="outflow">
        <!--      user can add his own phases to this area  -->
        <phase name="userphase1"/>
        <phase name="soapmonitorPhase"/>
        <!--system predefined phase-->
        <!--these phase will run irrespective of the service-->
        <phase name="PolicyDetermination"/>
        <phase name="MessageOut"/>
    </phaseOrder>
    <phaseOrder type="INfaultflow">
        <!--      user can add his own phases to this area  -->
        <phase name="userphase1"/>
        <phase name="soapmonitorPhase"/>
    </phaseOrder>
    <phaseOrder type="Outfaultflow">
        <!--      user can add his own phases to this area  -->
        <phase name="userphase1"/>
        <phase name="soapmonitorPhase"/>
        <phase name="PolicyDetermination"/>
        <phase name="MessageOut"/>
    </phaseOrder>

See the user guide for more info on axis2 modules.

Transports for HTTP Connection

Axis2 comes with two CommonsHTTPTransportSender which is based on commons-httpclient. The configuration of the transport is as follows,

Options.setTransportInfo(Constants.TRANSPORT_HTTP, Constants.TRANSPORT_HTTP, false);

It should be noted that axis2.xml should be configured to call the commons transports, with the statement,

...
<transportSender name="http" class="org.apache.axis2.transport.http.CommonsHTTPTransportSender"> 
   <parameter name="PROTOCOL" locked="false">HTTP/1.1</parameter> 
   <parameter name="Transfer-Encoding" locked="false">chunked</parameter>
</transportSender>
...

Data Binding Support

Xml-beans is used to provide data binding support. In Axis2, xml is manipulated via AXIOM, which is based on StAX API. XML give full schema support. Thus, serialization and de-serialization of Xml is handle in Axis2 via xml-data binding framework.

Best Usage

Axis1.x and Axis2 have different ways of seen the SOAP stack. So the best way to migrate can be done through following the User guide and Architecture guide properly in Axis2. Axis2 is straight forward and friendly.