You are on page 1of 16

Programming Web Services using Apache Axis

1) Introduction

The article titled Programming Web Services using Apache Axis shows how Axis Framework has simplified
the creation of Web Services. It will start with the definition of Web Services and its related terminologies like
SOAP and WSDL. Following that the ease with which Web Services are published are explained. The later
section explores about the various tools available in the Axis distribution like the Tcp Monitor, Soap Monitor,
Mapping between Java and WSDL. Finally the article ends up by giving a Sample Web Service Application
deployed in Axis.

• Page 1 - Introduction
• Page 2 - Utilities
• Page 3 - Sample Application
• Download Source Code
• Post your comments here

2) Web Services

2.1) Introduction

Web Services enables two applications running in two different machines to communicate. Data exchange
between two heterogenous applications can be possible with Web Services. Technically, Web Services uses
XML to exchange data between applications. Web Service is not a single technology, but instead it is a mix of
the following technologies.

• SOAP
• WSDL

Let us look into these two terminologies briefly in the following sections.

2.2) SOAP

SOAP, which stands for Simple Object Access Protocol, defines the Request and the Response message
format in a Web Service Application. Simply put, it is nothing but a XML structure adhering to a well defined
Schema. A Web Service client sends Request to a Web Service in the form of SOAP message and gets the
response back in SOAP message only. Let us look into the structure of the SOAP message in the following
section.

A SOAP message consists of a SOAP Envelope which forms the outer most layer and it merely serves as a
container for the SOAP Header and SOAP Body Elements. The SOAP Header will carry information that
doesn't constitute to the original part of the message. For example, a SOAP Header may carry some
Application Specific Information language such the Locale information. This SOAP Header is optional only.
They SOAP Body consist of the original data that needs to be processed by the Web Service Application.
Consider the following xml snippet which illustrates the SOAP message.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<soapenv:Header>
</soapenv:Header>

<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>

2.3) WSDL

Web Services Description Language (WSDL) is again a XML Document that describes the definition of Web
Services so that they can be accessible by the Client. Technically, WSDL Document contains the name of the
Web Services, the arguments it is going to accept, the URL through which it can be accessed. At a higher level,
WSDL contains two definition set, one is the Abstract Definition set which contains very generic information
about the various supported data-types along with the information pertaining to messages, port-types and
operations. The second is the information very specific to the type of protocol that can be used to access the
services, the supported protocol list, the URL information etc. Following is the structure of the WSDL Document.

<?xml version="1.0" encoding="UTF-8"?>

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://ttdev.com/ss"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SimpleService"
targetNamespace="http://ttdev.com/ss">

<wsdl:types>

<!-- Definition of types here -->

</wsdl:types>

<wsdl:message name="requestName">
<wsdl:part name="requestName"/>
</wsdl:message>

<wsdl:message name="responseName">
<wsdl:part name="responseName"/>
</wsdl:message>

<wsdl:portType name="serviceName">
<wsdl:operation name="operationName">
<wsdl:input message="requestName" />
<wsdl:output message="responseName" />
</wsdl:operation>
</wsdl:portType>

<wsdl:binding name="bindingName">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="operationName">
<soap:operation soapAction="someUrl" />

<wsdl:input>
<soap:body parts="requestName" use="literal" />
</wsdl:input>

<wsdl:output>
<soap:body parts="responseName" use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

<wsdl:service name="serviceName">
<wsdl:port binding="bindingName" name="bindingName">
<soap:address
location="ClientAccessibleUrl"/>
</wsdl:port>
</wsdl:service>

</wsdl:definitions>

One of the good things about the Axis Engine is that Developers doesn't really need to know the low-level
issues like the SOAP message, WSDL because they are given higher level of abstraction.

3) Utilities
Let us look into the following Utilities that comes along with Axis Distribution.

• Tcp monitor
• Soap Monitor
• Mapping between Java and WSDL File

3.1) Tcp monitor

Tcp Monitor can be used to monitor the Http Request and Http Response made to Axis Application. To start the
Tcp Monitor, have the following Utility file that starts the Gui for the Tcp Monitor Application,

RunTcpMonitor.java

package net.javabeat.apache.axis.webservices.playerservices;

import org.apache.axis.utils.tcpmon;

public class RunTcpMonitor {

public static void main(String[] args) {


tcpmon.main(args);
}
}

Enter some port number (other than 8080), say 9090 in the Listen Port Text Field and click the Add button. You
can see a new second tab opening in the same dialog. Now, launch the browser with the following URL,
'http://localhost:9090/axis'. Now go back to the Tab window to find the Request and the Response in the form of
Html format. By listening to the port 9090, whatever Request comes to port 8080, the Tcp Monitor simply
forwards the Request and Response to the listening port.
Http Request and Response monitoring using Tcp Monitor

3.2) Soap Monitor

SOAP Monitor functions very similarly like a Tcp Monitor. Whereas Tcp Monitor is used to intercept Http
Request and Http Response messages, SOAP Monitor is used to track the SOAP Request and SOAP
Response Messages. SOAP Monitor is implemented as a Handler and by default it is not enabled for all the
Web Services. If we want to enable SOAP Monitor Handler for both Request and Response SOAP messages,
then add the following entry in the deployment descriptor file for the Web Service.

<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

<service name="SomeService" provider="java:RPC">

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

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

<parameter name="className" value="SomeService"/>


<parameter name="allowedMethods" value="*"/>
</service>

</deployment>

Now, whenever, you request for a Web Service, the Soap Monitor will track the Request and Response from the
Web Service and will display the Xml Request and Xml Response content in the UI as shown below.
Soap Monitor monitoring the Soap Request and Soap Response.

3.3) Mapping between Java and WSDL File

Axis comes with Utilities that maps between Java Class and WSDL file Objects. For example, let us assume
that we have a WSDL file and we want to generate the various Java Classes that can be used to generate the
Client and the Server code describing the Web Service. For example, consider the following WSDL file that
represents the Add service with a simple add() operation taking two parameters. Following is the example
WSDL File,

AddServer.wsdl

<wsdl:definitions targetNamespace="http://localhost:8080/axis/services/AddService">

<wsdl:message name="addRequest">
<wsdl:part name="in0" type="xsd:int"/>
<wsdl:part name="in1" type="xsd:int"/>
</wsdl:message>

<wsdl:message name="addResponse">
<wsdl:part name="addReturn" type="xsd:int"/>
</wsdl:message>

<wsdl:portType name="AddService">
<wsdl:operation name="add" parameterOrder="in0 in1">
<wsdl:input message="impl:addRequest" name="addRequest"/>
<wsdl:output message="impl:addResponse" name="addResponse"/>
</wsdl:operation>
</wsdl:portType>

<wsdl:binding name="AddServiceSoapBinding" type="impl:AddService">


<wsdlsoap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="add">
<wsdlsoap:operation soapAction=""/>

<wsdl:input name="addRequest">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://addservice" use="encoded"/>
</wsdl:input>
<wsdl:output name="addResponse">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://localhost:8080/axis/services/AddService"
use="encoded"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

<wsdl:service name="AddServiceService">
<wsdl:port binding="impl:AddServiceSoapBinding" name="AddService">
<wsdlsoap:address
location="http://localhost:8080/axis/services/AddService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

To generate the various client and the server related Java files from the WSDL file, Axis provides a Utility called
WSDL 2 Java. For example, consider the following Java program makes use of the Utility.

AddWSDL2Java.java

import org.apache.axis.wsdl.WSDL2Java;

public class AddWSDL2Java {

public static void main(String[] args) {


WSDL2Java.main(new String[]{
"http://localhost:8080/axis/services/AddService?wsdl"});
}
}

It is important to understand that the default mappings for WSDL to Java. For example, the elements 'portType',
'binding' and 'service' in the WSDL file will be converted into its corresponding Java class type. In the WSDL, the
name of the portType is 'AddService' which has a single operation by name 'add' with two parameters called 'in0'
and 'in1'. For this, the corresponding class which is generated by the Utility looks like,

AddService.java

package localhost.axis.services.AddService;

public interface AddService extends java.rmi.Remote {


public int add(int in0, int in1) throws java.rmi.RemoteException;
}

The 'binding' element in the WSDL file specifies the type of binding (Rpc or Document) and its specifies the
protocol used to access the Web Service. It also defines the Encoding Mechanism used for the two input
parameters. For this, the corresponding class generated class s given below,

AddServiceSoapBindingStub.java
/**
* AddServiceSoapBindingStub.java
*
* This file was auto-generated from WSDL
* by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
*/

package localhost.axis.services.AddService;

public class AddServiceSoapBindingStub extends org.apache.axis.client.Stub


implements localhost.axis.services.AddService.AddService {

private java.util.Vector cachedSerClasses = new java.util.Vector();


private java.util.Vector cachedSerQNames = new java.util.Vector();
private java.util.Vector cachedSerFactories = new java.util.Vector();
private java.util.Vector cachedDeserFactories = new java.util.Vector();

static org.apache.axis.description.OperationDesc [] _operations;

static {
_operations = new org.apache.axis.description.OperationDesc[1];
_initOperationDesc1();
}

private static void _initOperationDesc1(){


org.apache.axis.description.OperationDesc oper;
org.apache.axis.description.ParameterDesc param;
oper = new org.apache.axis.description.OperationDesc();
oper.setName("add");

param = new org.apache.axis.description.ParameterDesc(


new javax.xml.namespace.QName("", "in0"),
org.apache.axis.description.ParameterDesc.IN,
new javax.xml.namespace.QName(
"http://www.w3.org/2001/XMLSchema", "int"),
int.class, false, false);
oper.addParameter(param);

param = new org.apache.axis.description.ParameterDesc(


new javax.xml.namespace.QName("", "in1"),
org.apache.axis.description.ParameterDesc.IN,
new javax.xml.namespace.QName(
"http://www.w3.org/2001/XMLSchema", "int"),
int.class, false, false);
oper.addParameter(param);

oper.setReturnType(new javax.xml.namespace.QName(
"http://www.w3.org/2001/XMLSchema", "int"));
oper.setReturnClass(int.class);
oper.setReturnQName(new javax.xml.namespace.QName("", "addReturn"));
oper.setStyle(org.apache.axis.constants.Style.RPC);

oper.setUse(org.apache.axis.constants.Use.ENCODED);
_operations[0] = oper;
}

public AddServiceSoapBindingStub() throws org.apache.axis.AxisFault {


this(null);
}

public AddServiceSoapBindingStub(java.net.URL endpointURL,


javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
this(service);
super.cachedEndpoint = endpointURL;
}

public AddServiceSoapBindingStub(javax.xml.rpc.Service service)


throws org.apache.axis.AxisFault {
if (service == null) {
super.service = new org.apache.axis.client.Service();
} else {
super.service = service;
}

((org.apache.axis.client.Service)super.service).setTypeMappingVersion("1.2");
}

protected org.apache.axis.client.Call createCall()


throws java.rmi.RemoteException {
try {
org.apache.axis.client.Call _call = super._createCall();

if (super.maintainSessionSet) {
_call.setMaintainSession(super.maintainSession);
}
if (super.cachedUsername != null) {
_call.setUsername(super.cachedUsername);
}
if (super.cachedPassword != null) {
_call.setPassword(super.cachedPassword);
}
if (super.cachedEndpoint != null) {
_call.setTargetEndpointAddress(super.cachedEndpoint);
}
if (super.cachedTimeout != null) {
_call.setTimeout(super.cachedTimeout);
}
if (super.cachedPortName != null) {
_call.setPortName(super.cachedPortName);
}

java.util.Enumeration keys = super.cachedProperties.keys();


while (keys.hasMoreElements()) {
java.lang.String key = (java.lang.String) keys.nextElement();
_call.setProperty(key, super.cachedProperties.get(key));
}
return _call;
}
catch (java.lang.Throwable _t) {
throw new org.apache.axis.AxisFault(
"Failure trying to get the Call object", _t);
}
}

public int add(int in0, int in1) throws java.rmi.RemoteException {


if (super.cachedEndpoint == null) {
throw new org.apache.axis.NoEndPointException();
}
org.apache.axis.client.Call _call = createCall();
_call.setOperation(_operations[0]);
_call.setUseSOAPAction(true);
_call.setSOAPActionURI("");
_call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
_call.setOperationName(
new javax.xml.namespace.QName("http://addservice", "add"));

setRequestHeaders(_call);
setAttachments(_call);

try {
java.lang.Object _resp = _call.invoke(new java.lang.Object[] {
new java.lang.Integer(in0), new java.lang.Integer(in1)});

if (_resp instanceof java.rmi.RemoteException) {


throw (java.rmi.RemoteException)_resp;
}
else {
extractAttachments(_call);
try {
return ((java.lang.Integer) _resp).intValue();
}catch (java.lang.Exception _exception) {
return ((java.lang.Integer)
org.apache.axis.utils.JavaUtils.convert(
_resp, int.class)).intValue();
}
}
} catch (org.apache.axis.AxisFault axisFaultException) {
throw axisFaultException;
}
}

Similarly, there is one more file generated for the 'service' element which contains the URL to access the Web
Service. Axis also provides Java2WSDL, which takes the Java interface having the various Web Service
operations as input and will generate the corresponding WSDL file that can be accessible by the Clients.

4) Sample Application

Let us finish off the article by giving a Sample Application. This Sample Application is all about querying
information from a Web Application. For this, let us assume that we have a mini Cricket Database maintained in
the backend and we publish the various services to the Client in the WSDL file. Both types of clients, Browser
Client and Console Client are included in the sample Application.

4.1) Pre-requisites

For the sample application to work, we need a Web Container (like Tomcat) along with the Axis Distribution.

• Axix – http://www.apache.axis.org
• Tomcat – http://www.apache.tomcat.org
After downloading these bundles make Tomcat point to Axis as a Web Application. To make this one happen,
follow the steps,

1. Go to AXIS_ROOT directory where you can find a directory called 'webapps'.


2. Copy the axis directory within the 'webaps' directory and paste it into TOMCAT_ROOT\webapps
directory.
3. Start the Tomcat Server by running the startup.bat in the TOMCAT_ROOT\bin directory.
4. Point to the Browser with the URL 'http://localhost:8080/axis/' (assuming that you are running the server
in your local machine with the default port number 8080) to see the following page.

Home page for Axis

4.2) Player.java

Let us model the properties of the player like the player name, the country to which he belongs to, age and the
number of runs scored in the Player class. Following is the implementation of the Player class which merely
contains the getters and the setters for the above mentioned properties.

Player.java

package net.javabeat.apache.axis.webservices.playerservices;

public class Player {

private String name;


private String country;
private int age;
private long runsScored;

public Player(String name, String country,int age, long runsScored){


this.name = name;
this.country = country;
this.age = age;
this.runsScored = runsScored;
}

public String getName() {


return name;
}

public void setName(String name) {


this.name = name;
}

public String getCountry() {


return country;
}

public void setCountry(String country) {


this.country = country;
}

public int getAge() {


return age;
}

public void setAge(int age) {


this.age = age;
}

public long getRunsScored() {


return runsScored;
}

public void setRunsScored(long runsScored) {


this.runsScored = runsScored;
}
}

4.3) Player Database.java

This is the Helper class which creates some Player objects during the start-up. This class will be used by the
Player Service class (which will be seen later) for querying the various player information. Following is the
implementation of the PlayerDatabase class.

PlayerDatabase.java

package net.javabeat.apache.axis.webservices.playerservices;

import java.util.*;

public class PlayerDatabase {

private static List<Player> players;

public static List<Player> list(){


return players;
}

public static Player getPlayer(String name){


Iterator<Player> iterator = players.iterator();
while (iterator.hasNext()){
Player player = iterator.next();
if (player.getName().equals(name)){
return player;
}
}
return null;
}

static {
initPlayers();
}

static void initPlayers(){


players = new ArrayList<Player>();
players.add(new Player("Tendulkar", "India", 34, 15000L));
players.add(new Player("Ganguly", "India", 35, 12000L));
players.add(new Player("Dravid", "India", 32, 11000L));
}
}

4.4) Player Service.java

We wish to publish the services of this class to the Clients. The Class given below has four services namely
getAgeForPlayer, getCountryForPlayer, getRunsForPlayer and listAllPlayers, the meaning of which is well
known from the name of the method names itself.

PlayerService.java

package net.javabeat.apache.axis.webservices.playerservices;

import java.util.List;

public class PlayerService {

public int getAgeForPlayer(String name){


return PlayerDatabase.getPlayer(name).getAge();
}

public String getCountryForPlayer(String name){


return PlayerDatabase.getPlayer(name).getCountry();
}

public long getRunsForPlayer(String name){


return PlayerDatabase.getPlayer(name).getRunsScored();
}

public String listAllPlayers(){


List<Player> players = PlayerDatabase.list();
StringBuilder result = new StringBuilder();

for(Player player : players){


result.append(player.getName() + " ");
}
return result.toString();
}
}
4.5) Deploying the Player Service

As we have seen already, the Admin Client Tility can be used for deploying and un-deploying a Web Service
Application. To make things simpler, let us have a simple Java class that does the job of deploying the Player
Service to Axis. Following is the code for the same.

DeployPlayerService.java

DeployPlayerService.java

package net.javabeat.apache.axis.webservices.playerservices;

import org.apache.axis.client.AdminClient;

public class DeployPlayerService {

public static void main(String[] args) {


AdminClient.main(new String[]{"src/deployment/player-service-deploy.wsdd"});
}

The above code references a Xml file called 'player-service-deploy.wsdd' which contains the information to
deploy the class PlayerService as a Web Service. Following is the code snippet for the Xml file.

player-service-deploy.wsdd

<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

<service name="PlayerService" provider="java:RPC">


<parameter name="className"
value="net.javabeat.apache.axis.webservices.playerservices.PlayerService"/>
<parameter name="allowedMethods" value="*"/>
</service>

</deployment>

As we can see, the service name is given as 'PlayerService' which is referring the class
'net.javabeat.apache.axis.webservices.playerservices.PlayerService' containing all the service methods. Also,
we have assigned the value '*' to the property 'allowedMethods' meaning that we have granted permission to
access all the public methods inside the PlayerService class. Before running the DeployPlayer class, make sure
the class-path is made to point the following jars.

• AXIS_ROOT\lib\activation.jar
• AXIS_ROOT\lib\axis.jar
• AXIS_ROOT\lib\axis-ant.jar
• AXIS_ROOT\lib\commons-discovery-0.2.jar
• AXIS_ROOT\lib\commons-logging-1.0.4.jar
• AXIS_ROOT\lib\jaxrpc.jar
• AXIS_ROOT\lib\log4j-1.2.8.jar
• AXIS_ROOT\lib\mail.jar
• AXIS_ROOT\lib\saaj.jar
• AXIS_ROOT\lib\wsdl4j-1.5.1.jar
• TOMCAT_ROOT\lib\xercesImpl.jar
• TOMCAT_ROOT\lib\servlet-api.jar

After successful deployment, you can see the following output made in your console,

Processing file src/deployment/player-service-deploy.wsdd


<Admin>Done processing</Admin>

To check whether the deployment has actually happened or not, launch your browser (with the Tomcat Server
running) to the following URL. http://localhost:8080/axis/servlet/AxisServlet. There you can see the Player
Service among the list of other Web Services, under which you can also find out the list of the operations
supported by the Service.

Player Service along the list of Web Services

4.6) Un-deploying the Player Service

Un-deploying the Service follows the same procedure as that of the Deployment , except that the Wsdd Xml file
should contain proper instructions for un-deploying a service. Following is the Xml file that un-deploys the Player
Web Service.

<undeployment xmlns="http://xml.apache.org/axis/wsdd/">
<service name="PlayerService"/>
</undeployment>

The code snippet is very simple as the name of the service is pointing to 'PlayerService' which we want to un-
deploy. Following is the Admin Client utility that should be run to un-deploy the service.

UnDeployPlayerService.java

UnDeployPlayerService.java

package net.javabeat.apache.axis.webservices.playerservices;

import org.apache.axis.client.AdminClient;

public class UnDeployPlayerService {

public static void main(String[] args) {


AdminClient.main(new String[]{"src/deployment/player-service-undeploy.wsdd"});
}
}

Running the above java program and open to the browser to the URL,
http://localhost:8080/axis/servlet/AxisServlet, to find the Web Service not listed in the page.
4.7) Invoking the Web Services

To invoke all the supported operations of the Player Web Service, first make sure that the class files
(Player.class, PlayerDatabase.class and PlayerService.class) are copied to
TOMCAT_ROOT\webapps\axis\WEB-INF\classes directory. Restart the Tomcat server and launch the Browser
to the following URL, http://localhost:8080/axis/servlet/AxisServlet'.

Use the following URL's to access the various web services operations

• http://localhost:8080/axis/services/PlayerService?method=listAllPlayers
• http://localhost:8080/axis/services/PlayerService?method=getRunsForPlayer&name=Tendulkar
• http://localhost:8080/axis/services/PlayerService?method=getCountryForPlayer&name=Dravid
• http://localhost:8080/axis/services/PlayerService?method=getAgeForPlayer&name=Ganguly

4.8) Creating a Console-based Client

Let us see how to access the Web Service using the Axis Client API with a normal Console Client. Following is
the code snippet for the same.

PlayerServiceClient.java

package net.javabeat.apache.axis.webservices.playerservices;

import java.net.URL;

import org.apache.axis.client.Service;
import org.apache.axis.client.Call;

public class PlayerServiceClient {

public static void main(String[] args) {

try{
URL url = new URL("http://localhost:8080/axis/services/PlayerService");

Service service = new Service();

Call call = (Call)service.createCall();


call.setTargetEndpointAddress(url);
Object result = call.invoke("listAllPlayers", new Object[]{});
System.out.println(result);

result = call.invoke("getRunsForPlayer", new Object[]{"Tendulkar"});


System.out.println(result);

result = call.invoke("getCountryForPlayer", new Object[]{"Dravid"});


System.out.println(result);

result = call.invoke("getAgeForPlayer", new Object[]{"Ganguly"});


System.out.println(result);

}catch(Exception exception){
exception.printStackTrace();
}
}
}

The above Client is making use of Axis specific API to access the Web Service. A Call
(org.apache.axis.client.Call) object encapsulates a Web Service, which should point to a URL as represented by
the Call.setTargetEndpointAddress(). A Call object is usually created using the Service object which is
represented by org.apache.axis.client.Service. Invocation of the Web Service operation is made by specifying
the operation name and the list of arguments it is going to accept through Call.invoke().

5) Conclusion
This article showed you how to write Web Servcies using the Apache Axis Framework. This Framework has
simplified the Developmental Process a lot by hiding many of the Xml Stuffs and the low-level Configuration
Details and has matured a lot. To summarize, this article initially explained the concepts like SOAP and WSDL
which are the core Components for any Web Service Implmentation. Then it explained about Tcp Monitor and
SOAP Monitor which are used to intercept Http/SOAP Request and Response. Then the Mapping Utilities for
the conversion between Java and WSDL file is covered in detail. Finally the article ended up by giving a Sample
Application along with the Clients.

You might also like