Publishing Your Java Class as a Web Service Using Axis2

In this tutorial, we will learn how we can publish your existing Java class as a Web service using Apache Axis2. We assume that we want to publish the following HelloWorld class as a Web service HelloService.
public class HelloWorld {
   public String sayHello(String name) {
      return "Hello " + name;
   }
}
Our HelloService will provide one operation, sayHello, that takes name as the input and returns the "Hello ..." string as the output.

There are two main steps involved in publishing a Web service from your Java code:

  1. Write a service description file (services.xml).
  2. Create a service archive file.

Writing the services.xml file

Once Axis2 receives a request to a Web service, it has to figure out which Java class can handle the Web service request. This "mapping" between a Web service and a Java class is described in services.xml file. Writing the services.xml file for our HelloService is quite simple. Essentially, the file should contain the following information:

For now, do not worry about the message receiver part, and look at the following services.xml file for our HelloService:
<service name="HelloService">
   <description>This is the HelloWorld service</description>
   <parameter name="ServiceClass">HelloWorld</parameter>
   <operation name="sayHello">
      <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
   </operation>
</service>

The second line in the above file provides a text description of the Web service and may be omitted.

Service implementation class: The third line indicates that this Web service is handled by the HelloWorld class. Since our HelloWorld class does not belong to any package namespace, the class name is specified simply as HelloWorld here, but in general the class name should be the fully qualified class name (like edu.ucla.cs.cs144.DemoService).

Message receiver: The fourth through sixth lines specify that the operation sayHello of this service should use the Axis2 Java class org.apache.axis2.rpc.receivers.RPCMessageReceiver as its message receiver class. A message receiver is the Axis2 Java class that processes the inputs to and outputs from the Web service, and pass them to/from our Java class. Axis2 provides a set of built-in message receiver classes depending on the message exchange pattern (MEP) of the Web service (e.g., input only? output only? input and output?) and the input/output encoding scheme used by the service; in our example, we are using org.apache.axis2.rpc.receivers.RPCMessageReceiver which is a common message receiver used for publishing an existing Java class.

Different way of specifying message receivers

In the above services.html file, we specified the Axis2 message receiver class at the operation level, associating a message receiver for every operation of our service. Axis2 also allows us to specify the message receivers at the service level, so that we can specify the message receiver once for the entire service as follows:

<service name="HelloService">
   <description>This is the HelloWorld service</description>
   <parameter name="ServiceClass">HelloWorld</parameter>
   <messageReceivers>
       <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
                        class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
       <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
                        class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
   </messageReceivers>
   <operation name="sayHello" />
</service>

Note that Axis2 has built-in support for all the eight MEPs (Message Exchange Pattern) defined in WSDL 2.0. In the services.xml file, we can specify the MEP and the corresponding message receiver, and then, Axis2 automatically picks up and uses the appropriate message receiver for each service operation. In the above file, we specify RPCInOnlyMessageReceiver as the message receiver for all input-only operations and RPCMessageReceiver as the message receiver for all input-and-output operations.

In the second last line, the operation element for sayHello shows this operation will be available by the service. This line is optional; by default, Axis2 exposes all public methods in the service implementation class whether we specify them in services.xml or not. For all public methods in the implemenation class, Axis2 calculates the MEP of the operation by checking the return value of the Java method. If the method is void, the MEP will be in-only; else, it will be in-out, depending on which the appropriate MEP message receiver will be set.

Creating a service archive file

Once we create our service description file services.xml, the final step before deployment is to create a service archive file by putting together (1) our service implementation class, (2) all libraries that it depends on, and (3) the services.xml file. These files should be placed in the appropriate directories within the archive file. For example, the directory structure of our HelloService archive file should be as follows:

HelloService.aar
 +- META-INF
 |    +- services.xml
 |
 +- HelloWorld.class

First note that the name of the archive file is HelloService.aar, which is the same as the name of the Web service that the archive file provides, followed by the extension .aar. If the name of our service were MyService, the file name would have been MyService.aar.

The services.xml file that we created in the previous step should be placed in the META-INF subdirectory of the archive file.

Depending on the namespace the class belongs to, the service impelementation class should be placed in the appropriate subdirectory of the archive file. In our example, the HelloWorld class does not belong to any package namespace, so it is simply placed at the root directory. All other classes that the implementation class depends on should also be placed at the appropriate directory.

Finally, if the implementation class uses any external Java libraries, they should be placed in the lib subdirectory of the archive file.

Here is a bit more complex example of the structure of an archive file:

AnotherService.aar
 +- META-INF
 |   +- services.xml
 |
 +- lib
 |   +- xxx.jar
 |
 +- edu
     +- ucla
         +- cs
            +- cs144
                +- AnotherClass.class

Here, the archive file handles the Web service named AnotherService and the service is implemented by the Java class edu.ucla.cs.cs144.AnotherClass. Assuming the class depends on the xxx.jar library, we placed it in the lib subdirectory of the archive file.

An archive file can be created using the jar command in the stadard Java Development Kit. For example, to create the above HelloWorld.aar file, first (1) create a temporary directory, (2) create the appropriate subdirectories within the temporary directory (like META-INF, lib, etc.), (3) place your class and library files at the appropriate subdirectories. Then inside the temporary directory, execute the following command:
jar cvf HelloService.aar *

The above command will create the HelloService.aar file and add all files below the current directory to the file. Once the archive file is created, deploying the service is just a matter of dropping the service archive file into the Axis2 services directory of our Tomcat server (which is $CATALINA_BASE/webapps/axis2/WEB-INF/services/). We can also easily upload the service archive file by using axis2 Web administration console.

In this tutorial, we went over the most basic elements of Axis2 service description file. If you want to know more about the syntax of the file, please read Writing Your Own services.xml for Axis2 Web Services (local mirror).