Tuesday, June 2, 2015

Publishing WebService using Axis2

Publishing REST ful WebService using Axis2


WSDL 2.0 HTTP Binding defines a way to implement REST (Representational State Transfer) with Web services. Axis2 implements the most defined HTTP binding specification. REST Web services are a reduced subset of the usual Web service stack.
  1. REST Web services are Synchronous and Request Response in nature.
  2. When REST Web services are accessed via GET, the service and the operations are identified based on the URL. The parameters are assumed as parameters of the Web service. In this case, the GET based REST Web services support only simple types as arguments and it should adhere to the IRI style.
  3. POST based Web services do not need a SOAP Envelope or a SOAP Body. REST Web Services do not have Headers and the payload is sent directly.
Axis2 can be configured as a REST Container and can be used to send and receive RESTful Web service requests and responses. REST Web services can be accessed using HTTP GET and POST.

The sample explains how to write a Web service and Web service client with 
Apache Axis2 using XML based client APIs (Axis2's Primary APIs).

First of all we will have to set up the Axis2 WAR to set up our REST container so that once we are ready with our service implementation and we have our .aar file generated  , we can get this deployed as a service on Axis 2 container.

The .AAR file will have META-INF holding services.xml which will have service implementation details:
      a. Service Class -> The actual Java class file holding implementation
      b. operation name -> The actual method name

1. Deploy Axis2 War on the local set up, I deployed my axis2.war under web apps directory of tomcat server as below ::



Deployed Services will be available on the below location after we execute build and get .aar file generated::

http://localhost:8080/axis2/services/

2. Create a Simple WebService which will just echo any String passed to it
import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import javax.xml.stream.XMLStreamException;
public class MyService {
    public OMElement echo(OMElement element) throws XMLStreamException {
        //Praparing the OMElement so that it can be attached to another OM Tree.
        //First the OMElement should be completely build in case it is not fully built and still
        //some of the xml is in the stream.
        element.build();
        //Secondly the OMElement should be detached from the current OMTree so that it can be attached
        //some other OM Tree. Once detached the OmTree will remove its connections to this OMElement.
        element.detach();
        return element;
    }
}

3.  Bundle in a Axis Archive file i.e .AAR file
     a. build.xml for Ant based build / aar file generation
   <project name="userguide1" default="generate.service">
    <property name="mainDir" value="../.."/>
    <property name="classes.dir" value="build/classes"/>
    <path id="axis.classpath">
        <fileset dir="../../lib">
            <include name="*.jar"/>
        </fileset>
        <pathelement location="build/userguide1.jar"/>
    </path>
    <mkdir dir="${basedir}/build/classes"/>
    <target name="run.client.all"
            depends="run.client.blocking">
    </target>
    <target name="compile">
    <mkdir dir="${classes.dir}" />
<javac srcdir="src" destdir="${classes.dir}">
<classpath refid="axis.classpath" />
</javac>
<jar destfile="build/userguide1.jar">
            <fileset dir="${classes.dir}">
                <include name="userguide1/**"/>
            </fileset>
        </jar>
    </target>
    
    <target name="generate.service" depends="compile">
            <jar destfile="build/MyService1.aar">
           <fileset dir="src/userguide/example1/">
               <include name="META-INF/**"/>
           </fileset>
           <fileset dir="${classes.dir}">
               <include name="userguide/example1/**/*.class"/>
           </fileset>
        </jar>
        <copy file="build/MyService1.aar" tofile="../../repository/services/MyService1.aar" overwrite="true"/>
    </target>
   <target name="run.client.blocking" depends="compile">
        <java classname="userguide.clients.EchoBlockingClient"
              classpathref="axis.classpath" fork="true">
            <jvmarg value="-Daxis2.repo=${mainDir}/repository"/>
    <jvmarg value="-Daxis2.xml=conf/axis2.xml"/>
        </java>
    </target>
    <target name="run.client">
<echo message="Please use the following ant targets to run the clients" />
<echo message="run.client.all  -  run all clients" />
    </target>
    <target name="clean">
<delete dir="build" />
    </target>
</project>

c. Execute ant / build.xml and get the MyService1.aar generated which will be using the below src code.

    i) services.xml
            <service name="MyService1">
                      <description>
                      This is a sample Web Service with an echo operations
                        </description>
                 <parameter name="ServiceClass">userguide.example1.MyService</parameter>
                <operation name="echo">
               <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
               <actionMapping>urn:echo</actionMapping>
               </operation>
             </service>

     ii) MyService.java

import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import javax.xml.stream.XMLStreamException;

public class MyService {
    public OMElement echo(OMElement element) throws XMLStreamException {
        //Praparing the OMElement so that it can be attached to another OM Tree.
        //First the OMElement should be completely build in case it is not fully built and still
        //some of the xml is in the stream.
        element.build();
        //Secondly the OMElement should be detached from the current OMTree so that it can be attached
        //some other OM Tree. Once detached the OmTree will remove its connections to this OMElement.
        element.detach();
        return element;
    }
}

d. Once build is completed the generated MyService1.aar file will be placed fine in the services of Axis repository, if it does nt get hot deployed on the running Axis2 container which is hosted on any Tomcat server, then you can restart service by axis2server.bat

Once deployed the newly made service will be available under below location::
C:\Softwares\axis2-1.6.2\repository\services


e. Verify if the service is properly deployed:

http://localhost:8080/axis2/services/



d. Test the Service using REST based call via simple java class by hitting the URL ::
     http://localhost:8080/axis2/services/MyService1?wsdl
import javax.xml.namespace.QName;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;


public class RESTClient {

    private static String toEpr = "http://localhost:8080/axis2/services/MyService1?wsdl";
    
    @SuppressWarnings("deprecation")
public static void main(String[] args) throws AxisFault {

        Options options = new Options();
        options.setTo(new EndpointReference(toEpr));
        
        options.setProperty(Constants.Configuration.ENABLE_REST, Constants.VALUE_TRUE);

        ServiceClient sender = new ServiceClient();
        sender.engageModule(new QName(Constants.MODULE_ADDRESSING));
        sender.setOptions(options);
        OMElement result = sender.sendReceive(getPayload());

        try {
            XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(System.out);
            result.serialize(writer);
            writer.flush();
        } catch (XMLStreamException e) {
            e.printStackTrace();
        } catch (FactoryConfigurationError e) {
            e.printStackTrace();
        }
    }
    private static OMElement getPayload() {
        OMFactory fac = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace("http://example1.org/example1", "example1");
        OMElement method = fac.createOMElement("echo", omNs);
        OMElement value = fac.createOMElement("Text", omNs);
        value.addChild(fac.createOMText(value, "Axis2 Echo 2323232 String "));
        method.addChild(value);

        return method;
    }
}


And on execution we have the below response from Echo Service client

<example1:echo xmlns:example1="http://example1.org/example1">
<example1:Text>Axis2 Echo 2323232 String </example1:Text>
</example1:echo>

No comments:

Post a Comment