Getting started with Web Services Using Apache Axis
NOTE:This article pertains to Beta 2 of Apache Axis,
released in April 2002.
In this article, I will discuss the basics of web services
and explore how Apache Axis, an open-source SOAP toolkit, and can be
used to create, deploy, and access such services. After a quick
introduction, we'll discuss downloading and installing Axis.
Then, we'll build a simple web service and communicate with it.
Finally,
we'll discuss some of the details behind a more advanced example.
Introduction
Web services technology has quickly become an important enabler
of true distributed computing over the Internet. By using
web services, consumers and providers of functionality can
quickly connect, without the usual integration hassles, in
a way that is language-independent and platform-independent. For
example, if you develop remote functionality in C++ on a Microsoft
Windows NT system, your friend using Java on Sun Solaris will be
access it over the Internet.
To motivate the need for web services, let's consider an example.
Suppose you have developed a useful Java class that you would
like to distribute to others via the Internet. How would you
(at Internet site x) make Java functionality accessible to
your remote friend (at Internet site y)?
One option is to use something like Java IDL (i.e., CORBA).
After all, doesn't CORBA and the IIOP protocol allow distributed objects
(potentially written in different languages) to communicate with
each other over the Internet? Well, yes and no. CORBA-IIOP solutions,
while possible, can be problematic in terms of security and ease of
deployment. In terms of security, ensuring that IIOP will work
through firewalls is often painful, since IIOP traffic does not
travel on port 80, as does normal HTTP traffic. A second major
issue is the lack of simple deployment. Unless they want to really
do some lower level programming, both participants in an IIOP exchange
must have Object Request Brokers (ORBs), which manage objects locally
and route requests to available instances. There are other issues,
but we don't have the space to get into a full-blown debate.
However, in all fairness, I should at least note that there do exist
counter-arguments
.
Well, what about skipping all of this complexity and just using servlets?
For example, you could embed your functionality in a servlet and
route its output back to callers. However, doing so involves a lot
of ugliness:
- You have to build servlet wrappers for each piece of
functionality you want to deploy.
- You need to manually print the output of the Java methods
of interest.
- All variable types have been lost (unless you describe them explicitly -- and all your clients know about and obey your cooked-up protocol)
What we really want is some way to combine the flexibility and
interoperability of CORBA with the ease of deployments that
Java servlets provide. So, does such as solution exist? As it turns out,
it does: web services.
Web Services
Web services leverage the de-facto platform indepedence of the
Web and the extensibility and flexibility of XML to simplify distributed
computing on the Internet. The concept is straightforward: those that want
to distribute functionality publish web services, those that
want to use that functionality access those services.
The conceptual web services technology stack is shown in Figure 1.
| Figure 1 |
Let's start by explaining a few of the acronyms:
- WSDL: Web Services Description Language, which is how web services
are declared.
- SOAP: Simple Object Access Protocol, which is the mechanism for
how services are invoked.
- UDDI: Universal Description, Discovery, and Integration
specification, which is how services can be located.
There are
a variety of transports that one can use to communicate with
a web service - RPC, email, FTP, and HTTP, for example. In this
short tutorial, we will focus on HTTP, since that is the
protocol most readers will likely find applicable.
So then, in a nutshell, the technology stack in Figure 1 describes
how web services can be described, deployed, and accessed. In this
article, we will assume that we know the web service we want and where
it is deployed; thus, it only makes sense that access (SOAP) is our
chief concern. And this is exactly where Apache Axis comes in.
Apache Axis
Apache Axis is
a SOAP toolkit that makes it easy to create, deploy, and consume web
services. By using Axis, you will be able to quickly convert existing
Java functionality into web services, deploy those services, and be able
to communicate with them remotely via the Internet, usually through
firewalls (if necessary).
More precisely, Axis is an implementation of SOAP. Most people
like to think of it as a toolkit. From the programmer's point of
view, it's like an API. It makes it easy for you to communicate -
with SOAP - to a remote object, without having to worry about the
details associated with the protocol. In practice, it is a lot
like using RPC, CORBA, RMI, or any of the other distributed
computing technologies you may have experience with. The
process is largely the same: you describe the target of
your communication, invoke the remote method and marshall
your parameters, and then demarshall the return values.
Since AXIS makes this process simpler than ever, development
is a breeze.
The SOAP Protocol
SOAP is a simple an extensible protocol for communication between
application-level objects. It is a standard that originated between
a number of vendors, including Microsoft and IBM. However, its
support has grown to include Sun and is now generally viewed as the
best open standard for structured communication between objects
on the Web.
As described above, SOAP messages are
encoded with XML and the protocol can be deployed over a variety of
transports. In contrast to other synchronous protocols, SOAP communication
is one-way: from sender to receiver. Upon this, higher-level
request-response designs can be implemented.
A SOAP message consists of an envelope that contains an optional SOAP
header and a mandatory SOAP body.
The header is a mechanism for extensibility; we won't worry about
it much more here. The body contains the guts of the communication
between parties. For example, the body could contain information
on the remote method to be called, on the parameters to call it
with, etc. As a detailed example of a SOAP message, consider
the simple example (note that there is no header here -- remember,
it is optional) shown in Figure 2.
| Figure 2 |
This example illustrates a request to a SOAP node such that
the method "GetCurrentTime" is invoked with the parameters
"city" (Las Vegas) and "state" (of Nevada). The service
containing that method is found at example.com. With this
simple example, you now have a feel for what SOAP messages look like.
If you are interested in a more detailed description of the
SOAP protocol, check out the W3C note.
For our discussion here, I summarized SOAP messaging for the purposes
of underscoring that:
- SOAP messages are encoded with XML and thus make it a message-based
protocol.
- Methods and parameters can be declared in a SOAP message, but
they ultimately are associated with service and typing information
(such as whether the parameters are integers, floating points, etc.),
so that translation of those messages is proper and accurate.
- SOAP is a relatively simple protocol.
If you inferred that much from the above, you got the major points.
Time to move on.
Getting started
In the rest of this article, I will describe what you need to do to get
started with Axis. Afterwards , you should be able to:
- Download and install Axis
- Create and deploy web services
- Access those services remotely over the network
Although it is possible to describe how to generally use Axis, I
am going to take a more "in the trenches" approach, since I want
you to be able to run the examples I describe. Although the existing
Apache Axis documentation does a fine job of getting you started,
it does take a little while to identify some of the key configuration
issues. My hope is that this document streamlines that process
even more.
Assumptions and Dependencies
First, keep in mind that this article pertains to the Beta 2 of
Apache Axis, released in April of 2002. Pre-production open source
software often changes and it may be possible that post-beta-2
changes make some of this document invalid, so please consider
that if trying to use this document with any other release of
Axis.
Second, since this document goes into the details of configuring Axis,
it makes some assumptions:
- You are using Microsoft Windows 2000.
- You have the Java 1.3 JDK
- You have TCP/IP network access.
- You have no services running on port 8080 of your machine
(although you could easily adapt the examples below if you do).
Third, before you get started with Axis, you also need to have a J2EE
compliant subsystem that implements the Java 2.2 Servlet specification.
A good candidate for that is the
Apache Tomcat
Java servlet container. This tutorial assumes that you are using
the latest (at least at this time!) stable version: Tomcat 4.03.
As you know, you can run Tomcat independent of your web server.
It runs on a specified port (8080 by default) and can be started
up with a simple boot script that is included with the release.
You can install Tomcat anywhere on your machine. It will likely
choose c:\Program Files\Apache Tomcat 4.0 by default. Whether it
is this or another location of your choosing, no matter - the
point of installation is referred to hereafter as $TOMCAT_HOME.
Now, just to make sure no odd problems occur during our installation
of Axis, make sure that Tomcat is not running. We will
start it up later.
Finally, to parse the XML, you need to have an XML parsing
library available, such as Xerces or the Java API for XML Processing (JAXP).
Opting for an all-Apache approach, I used
Xerces 2.0.1,
which comes with the following libraries (available in the top level
directory of the Xerces release):
- xmlParserAPIs.jar
- xercesImpl.jar
- xercesSamples.jar
You probably only need the first two of these JAR files, but it is
important that you have Xerces 2 and that you know where these files are.
You will need them later.
Downloading, Installing, and Configuration
In this section, I describe how to download and configure Apache
Axis as a web application for your servlet container (Tomcat).
Once installed, clients will be able to access SOAP nodes on your
server via an Apache Axis servlet.
The first step is to download the
Axis release. This is usually
a ZIP file. At the time of this writing it was located
here.
You can install this release anywhere on your machine; for example,
I installed it under c:\Program Files\Apache Group\xml-axis-beta2.
The second step is to integrate Axis as a web application of
Apache Tomcat. This step is extremely simple: just copy (recursively)
the webapps/axis directory under the webapps directory of your
Tomcat installation (i.e., $TOMCAT_HOME\webapps). Next,
copy the XML parser libraries (such as the 3 Xerces JAR files mentioned
above) to the $TOMCAT_HOME\webapps\axis\lib directory.
Next, a very important point that is sort of buried in the
current Axis instructions and FAQ: relocation of the RPC library Axis uses.
Specifically, you need to move (or copy) the file lib/jaxrpc.jar to
common/lib directory, under your Tomcat home (i.e.,
$TOMCAT_HOME\common\lib).
Finally, one point about setting up your environment.
Later in this article, you will need to compile some Java classes.
To do so means that you need to setup your classpath to use the
Axis libraries. I find it most simple to define a setup file
that augments the classpath to include the following libraries
(all found in $AXIS_HOME/lib):
- axis.jar
- commons-logging.jar
- log4j-core.jar
- jaxrpc.jar
- tt-bytecode.jar
- wsdl4j.jar
- the XML libraries associated with your parser, such as
xercesImpl.jar (or whatever your XML parser requires)
and xmlParserAPIs.jar
Before moving on, it might be useful to do a sanity check and
make sure that Tomcat works fine outside of Axis. That way, if
you have a problem in the next section, you can potentially
rule out Tomcat. So, for example, you should be able to
point your web browser at
http://localhost:8080/examples/servlets/index.html
and be able to execute the Hello World servlet example.
Web services made easy
Okay, you've downloaded and installed everything. You've ensured
that Tomcat works. Time to start building and testing out web
services with Axis. We'll start out with a very easy
example - this should quickly convince you how easy it is
to deploy web services with Axis.
Turning Java classes into instant web services
The easiest way to get started is to simply copy any
independent Java class into your Axis web application
directory and access it via SOAP remotely. This is easier
than you think. There are only three steps involved: (a) developing
the Java class, (b) deploying it, and (c) building and running
a client to access it.
The first step is to develop a Java class. Let's keep things
really simple and try out a Hello World -style class. We'll
develop one method, called greet() that takes someone's name
as a parameter and returns a nice greeting message with that
person's name.
To do this, locate the $AXIS_HOME/samples directory. Create
a new subdirectory called "hello". In this subdirectory,
create the file Hello.java, and include the following code:
public class Hello
{
public String greet(String a_name)
{
return "Nice to meet you, "+a_name;
}
}
NOTE:We're keeping Hello.java in the $AXIS_HOME/samples/hello
directory to keep things consistent with the rest of the Axis
built-in examples.
Now, do NOT compile Hello.java. Just copy it into
$TOMCAT_HOME/webapps/axis and name it Hello.jws. Clients (such
as the one we develop next) will request this service and the Axis
servlet will compile and execute our Hello.java class on the fly!
As you can see, developing a web service could not be more
painless. We didn't have to use a single library or implement
a single interface.
Accessing a web service
Time to build a client to access our service. This is where
we finally see some library code. But, as you will soon notice,
it's very simple and straightforward.
Again, to keep things consistent with the examples provided
by the Axis release, let us develop our client code in the
file HelloClient.java, which we will store at $AXIS_HOME/samples/hello.
In an abstract sense, HelloClient.java needs to do the following:
- Connect to the our Hello service (a SOAP endpoint)
- Invoke the service method remotely, marshalling parameters
in and out.
- Print out the reply from the service.
Below is code for HelloClient.java that enables this:
1 package samples.hello;
2
3 import org.apache.axis.client.Call;
4 import org.apache.axis.client.Service;
5 import org.apache.axis.encoding.XMLType;
6 import org.apache.axis.utils.Options;
7
8 import javax.xml.rpc.ParameterMode;
9
10 public class HelloClient
11 {
12 public static void main(String [] args)
13 throws Exception
14 {
15 Options options = new Options(args);
16
17 String endpoint = "http://localhost:" + options.getPort() +
18 "/axis/Hello.jws";
19
20 args = options.getRemainingArgs();
21
22 if (args == null || args.length != 1) {
23 System.err.println("Usage: Hello ");
24 return;
25 }
26
27 Service service = new Service();
28 Call call = (Call) service.createCall();
29
30 call.setTargetEndpointAddress(new java.net.URL(endpoint));
31 call.setOperationName("greet");
32 call.addParameter("name", XMLType.XSD_STRING, ParameterMode.IN);
33 call.setReturnType(XMLType.XSD_STRING);
34
35 String msg = (String)call.invoke(new Object[] {args[0]});
36
37 System.out.println("Reply: " + msg);
38 }
39 }
Here, there are obviously a few more things to note. Let's
take them one at a time.
- Line 1: We place our code in the samples/hello package, to keep
things consistent with the other Axis examples.
- Lines 15-20: We collect runtime options, such as the port
number of the destination service and the arguments to that service.
- Lines 27-33: We set key parameters of our call to the remote
method. This is the heart of the client, where we set our
endpoint, describe the method we want to invoke and the parameters we
are providing, and then declare the return type of that method.
This prepares the remote call.
- Line 35: We invoke the remote method and cast the
return object, since we know what know the type it will return.
Note that our runtime argument is passed in as a parameter as
part of an Object array. Thus, integers, strings, and other types
can be mixed (heterogenously) in this array for other types of
methods.
- Line 37: We print out the reply.
Now, we can simply compile this client, specifically:
javac samples/hello/HelloClient.java
and then run the client:
java samples.hello.HelloClient -p8080 Greg
which returns the message:
As you can see, development is pretty simple with Axis.
It hides behind the scenes and makes SOAP-based connectivity quick
and painless. Part of the magic behind why you were able to simply
copy the Hello.java file and have it accessible to your client
has to do with the $TOMCAT_HOME/webapps/axis/WEB-INF/web.xml
deployment descriptor file. In that file, you will find
the following section:
| Figure 3 |
These instructions tell Tomcat to run the Axis servlet on
all requests to files that end in .jws. You'll also notice
that the compiled class is stored in $TOMCAT_HOME/webapps/axis/WEB-INFjwsClasses as Hello.class.
Wait, where's the SOAP?
The Axis API does such a good job of hiding the details
in example above, you're probably wondering: where is the SOAP?
Actually, on the wire, XML-encoded SOAP messages are being exchanged.
Axis comes with a tool called tcpmon that allows you to
see this (it monitors the target TCP port). If you were to look
at it, the request would look something like what you see in
Figure 4 and the reply like you see in Figure 5.
| Figure 4 |
| Figure 5 |
A more advanced example
As the Axis documentation suggests, there are a variety of cases
where you cannot simply copy your Java source files into the
web application deployment directory. You may not have the source
code or you may want to use other handlers during processing, etc.
Both reasons motivate us to look at a more general method for deploying
and accessing services with Axis
In this example, let us focus on the development and deployment
of a service that we will call "LoudService". This service takes
an input string and returns the uppercase form of the string, as
if the string were being spoken loudly.
The steps involved in development and deployment are:
- Development of the LoudService class
- Development of a LoudService client
- Development of the deployment descriptor
- Deployment of the service using the descriptor
- Access by the client
Previously, steps 3 and 4 were hidden from us; now we will
perform them explicitly.
Developing the LoudService
The code for LoudService is just as simple as the code for the
Hello service we developed earlier:
package samples.loud;
public class LoudService
{
public String serviceMethod(String msg)
{
return msg.toUpperCase();
}
}
Let us store this file in a new directory at $AXIS_HOME/samples/loud.
We can compile this file and store the resulting LoudService.class
in another new directory, this time under the Tomcat hierarchy:
$TOMCAT_HOME/webapps/axis/WEB-INF/classes/samples/loud.
Developing the client
Developing the client is not that much different from what
we did earlier. As the code below shows, the main difference
is that we use the QName API to specify the name of the service (LoudService)
and the method (serviceMethod) we intend to execute.
Notice that the endpoint URL is obtained automatically (in this
case, it is: http://localhost:8080/axis/servlet/AxisServlet --
the class and method are resolved dynamically at runtime).
package samples.loud;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.apache.axis.utils.Options;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.namespace.QName;
public class Client
{
public static void main(String [] args)
{
try {
Options options = new Options(args);
String endpointURL = options.getURL();
String msg = null;
args = options.getRemainingArgs();
if ((args == null) || (args.length != 1)) {
System.err.println("You must send something.");
System.exit(-1);
} else {
msg = args[0];
}
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpointURL));
call.setOperationName(new QName("LoudService", "serviceMethod"));
call.addParameter("mesg", XMLType.XSD_STRING, ParameterMode.IN);
call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);
String reply = (String)call.invoke(new Object[] {msg});
System.out.println("Reply: "+reply);
}
catch (Exception e) {
System.err.println(e.toString());
}
}
We can then store this file in $AXIS_HOME/samples/loud and compile
it with the Java compiler.
Developing the deployment descriptor
The Axis web services deployment descriptor (WSDD) is an XML-encoded way of
specifying details about how SOAP-accessible functionality can
be deployed. There are a variety of options for deployment, but
we'll focus on the simple task of deployment as a web service.
The type of descriptor we need is shown in Figure 6. We don't have
the space to go into all of the options for how to deploy services;
but, using the example below, you should be able to get an idea.
|
Figure 6 |
We name this descriptor deploy.wsdd and store it in
$AXIS_HOME/samples/loud.
Deployment and client access
Now it is time to deploy our new service. To do that,
we use the Axis administrative service and call it with
the deployment descriptor above:
java org.apache.axis.client.AdminClient deploy.wsdd
The admin service reports that the service was loaded and
now you can use the client to access this service.
java samples.loud.Client "what did you say?"
which returns
Although this example was a little more complicated because
of the deployment considerations, we see that it is not terribly difficult
and in return we gain greater flexibility.
Conclusion
Of course, there are many more features and interesting details
related to Apache Axis than we can cover here. However, the
two examples we discussed above should hopefully clarify where
Axis fits in the overall web services architecture, give you a better
understanding about what Axis can do, get you started using its tools
and libraries, and leave you curious about more advanced features.
As you can Axis is simple,
easy to use, and powerful. We can deploy web services from
existing functionality in a very short time and thus
rapidly move towards true Internet distributed computing.
Return to Top
|