Tech Ads

Back to Article List

Originally published January 2004 [ Publisher Link ]

Java Web Services with Axis


Axis is the Apache Software foundation SOAP engine designed for deploying Web services. Although it's available for both Java and C++ environments, in this article we will deploy a Java Web service in conjunction with Tomcat, Apache's other open source project for a J2EE-Servlet/JSP container.

Don't let the name "Java" Web services mislead you; a Web service by definition is interoperable on various platforms and can be called from and even written in a plethora of languages, including C++, Perl, and PHP.

Before we begin, make sure you have Tomcat 5.x and Axis 1.1. Tomcat will serve as our server-side environment for deploying the Web service. You can get away with using another servlet/JSP engine or J2EE-compliant server like JBoss, WebLogic, or WebSphere, since Axis is configured and deployed at the Web Archive level, but the finer details in this article will address Tomcat.

The Web service

As its name implies, a Web service is just a service that is enabled to operate on the Internet. The following Web service is a Java class that, when given a price range, returns an answer based on the input:

public class Sales {

  public String onsale(int low, int high)
  {
    if (low < 1) {
     return "We have some bargains, but not at 
            those prices!";
    } else if ( high < 15 ) {
     return "We have all the Linux distros that fit 
            your price range!";
      } else {
     return "You have a good budget, please visit our
            site for more information!";
      }
  }
}

Notice that even though we will be using a servlet/JSP environment, the Java code is neither a servlet nor JSP. It is just a plain vanilla class, so it can interact with any agent or process. A servlet or JSP is generally designed for interaction with browsers only.

Though this Web service responds with static information, a real implementation would typically interact with a database or other source of information. For simplicity's sake I coded the data directly in this example.

Axis has two ways of deploying a Web service, which directly affects the manner in which you code it:

  • Web services ("Compiled"): This is what you would typically expect from a Java deployment. The Web service class is compiled into a .class file as with any other Java class.
  • Web services ("Source/.jws"): This allows you to use your Web service source code directly for deployment. You simply name your source code class with the .jws extension (for Java Web Services) instead of the classical .java.

Configuring the Web service

Web services in the Java version of Axis are configured in a Web Archive (WAR), which is how you deploy applications in a J2EE-Servlet/JSP container. The following diagram illustrates the structure and components that should be present when deploying a Web service via Axis:

+-/mytomcathome/webapps+--\
                          |
 /------------------------/
 |
 \ +-axis-+
          |
          |-Sales.jws ("Source Web-Service/*.jws")
          |
          +-WEB-INF+
                   |
                   +-web.xml
                   |
                   +-classes--+
                   |          |
                   |          +- Sales.class
                   |           ("Compiled Web-Service")
                   |
                   +-lib--+
                          |
                          +- axis-ant.jar
                          +- axis.jar
                          +- commons-discovery.jar
                          +- commons-logging.jar
                          +- jaxrpc.jar
                          +- log4j-1.2.8.jar
                          +- saaj.jar
                          +- wsdl4j.jar

The WAR structure is appended to a directory named mytomcathome/webapps/axis, where mytomcathome represents your Tomcat home directory and webapps is the default directory in which applications are placed; the axis directory represents our Java context, which in a default configuration would be accessible from a URL like http://localhost/axis, where localhost is your Web site's name.

Directly under the root directory of the context we place our source code Web service, the one with a .jws extension. Nested within is the WEB-INF directory, which contains the Web Archive configuration file web.xml; the classes sub-directory, which holds our compiled Web service Sales.class; and the lib directory, which includes all of Axis's core JAR files, which are included in the Axis distribution.

This next table illustrates the contents of the configuration file web.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.3.dtd">

<web-app>

<!-- Servlet Definitions -->

  <servlet>
    <servlet-name>AxisServlet</servlet-name>

    <servlet-class>
        org.apache.axis.transport.http.AxisServlet
    </servlet-class>
  </servlet>

  <servlet>
    <servlet-name>AxisAdminServlet</servlet-name>

    <servlet-class>
        org.apache.axis.transport.http.AdminServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

<!-- Servlet Mappings -->

  <servlet-mapping>
    <servlet-name>AxisServlet</servlet-name>
    <url-pattern>*.jws</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>AxisServlet</servlet-name>
    <url-pattern>/servlet/AxisServlet</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>AxisServlet</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>


  <servlet-mapping>
    <servlet-name>AxisAdminServlet</servlet-name>
    <url-pattern>/servlet/AxisAdminServlet</url-pattern>
  </servlet-mapping>

</web-app>

The first part of the deployment descriptor defines two servlets, one named AxisServlet, which can be considered the core SOAP engine in charge of processing and returning Web services results, and an ancillary servlet named AxisAdminServlet, which is used to monitor Axis. These servlets are mapped to corresponding classes included in the Axis distribution itself, the JAR files mentioned previously.

The other contents in web.xml define the URL mappings on which these servlets will be invoked. In other words, you are declaring at which location Axis will be processing Web services. The first three definitions indicate that any URL with an extension .jws or the URL /servlet/AxisServlet, as well as anything under the /services/ directory, will be processed by the AxisServlet, which for practical purposes represents the SOAP engine in itself.

Finishing off the descriptor file, we indicate that when the URL /servlet/AxisAdminServlet is visited it is to be processed by the AxisAdminServlet. Keep in mind that these URLs are all relative to your deployment, which in this case would be http://localhost/axis/<Relative URLs>.

So far so good. Start up your Tomcat instance and take a look at the following URLs with your browser:

  • http://localhost/axis/servlet/AxisAdminServlet: This outputs a page indicating Axis status.
  • http://localhost/axis/servlet/AxisServlet: This displays the list of Web services that are currently deployed in Axis, including a corresponding link to their Web Services Description Language (WSDL) files, which are used in the creation of the Web services client -- a subject that we will address in a bit.
  • http://localhost/axis/Sales.jws: This displays a notice indicating that a Web service is accessible at this location, as well as the corresponding link to its WSDL file.

After visiting the previous locations, you probably realized that in the list of deployed Web services your Sales class was nowhere to be found. There are a few good reasons why this is so:

  • Location: Nothing can be assumed regarding the place you want your Web service to be activated. There is the possibility you might want it deployed under various URLs or perhaps under a particular directory.
  • Security: Since your service will be available to the public at large, you will want to restrict usage based on some security credentials like username/password or IP address.

You get the idea, right? In our next article we will describe how to activate your Web service so you can view it from the Axis console and access it from a Java client.

Daniel Rubio is the principal consultant at Osmosis Latina, a firm specializing in XML and Java training and consulting based in Mexico.

Building Java Web Services with Apache Axis, part 2

In our previous article, we installed Apache Axis and created a Web service. Now we'll activate the Web service so you can view it from the Axis console and access it from a Java client. This step is not required for source-code Web services, since their location is already hardcoded in the WAR structure, but only for compiled Web services.

Axis provides a command line tool thorugh the org.apache.axis.client.AdminClient class for activating Web services. It takes as an input file a Web Services Deployment Descriptor. Based on XML, its syntax describes the characteristics a Web service should take upon deployment. Its structure can become quite complex depending upon the accessibility and security credentials you want your Web service to take. For our case, we will describe the most basic WSDD file needed to achieve the deployment of our Web service:

<?xml version="1.0" encoding="ISO-8859-1"?>

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

   <service name="Sales" provider="java:RPC">
       <parameter name="className" value="Sales"/>
       <parameter name="allowedMethods" value="*"/>
   </service>

</deployment>

Nested within the root <deployment> tag we can find the <service> tag, which defines the Web service deployment parameters. The tag in itself has the name attribute, which indicates the deployment name for the Web service. Rounding off this declaration, we encounter two <parameter> tags, one of which defines the Java Class that holds the Web service, and another for defining the callable methods in it. This corresponds to the Sales class and all of its methods (*) respectively.

Once you create the WSDD file, execute the following command to activate your Web service:

 java org.apache.axis.client.AdminClient Sales.wsdd

 (Where Sales.wsdd is your WSDD file)

Executing the previous command requires you to be in-line with the following requirements:

  • Loading Axis JAR files: The org.axis.client.AdminClient class, which is used to deploy Web services, is part of the Axis distribution. You must have all of the Axis JAR files (the same ones you placed in your WAR structure) defined in your CLASSPATH environment variable or declared at run-time with the -cp flag.
  • Default Web site: The default execution of org.axis.client.AdminClient assumes that you will deploy your Web service under a standard Tomcat installation. If your Tomcat and Axis deployment run on a URL other than the default http://localhost:8080/axis you need to indicate the proper flags at the command line: -h for the Hostname, -p for port number, and -s for the AxisServlet location.

Once you successfully run your WSDD file, you can look at your Axis console (found at http://localhost/axis/servlet/AxisServlet) and see your deployed Sales Web service.

If you recall, when visiting the URL for your non-compiled Web service (.jws) at http://localhost/axis/Sales.jws you could also find a link prefixed with the initials WSDL. This same type of link now appears on your Axis console with your Sales Web service. This link and the content it generates are key for accessing your Web service, since WSDL is an intricate part of the Web services puzzle.

WSDL for the Web service

Web Services Description Language is the standard language in which you describe Web services. Based on XML, it allows you to map a service in a language-agnostic manner.

The WSDL contract Axis creates for you can be used to generate a Web services client in any language or platform that supports Web services. In other words, if you provide this contract to your business partners or users, they can write a program in whichever language they prefer (PHP, C++, VisualBasic) to call your service, without even knowing your Web service is written in Java.

As interesting as it would be to code a client in another language for calling our Java Web service, we will stick to our primary language and write a Java client for our Web service.

The Web service client

A Java Web service client, like any other Web service client, does not have to take any particular form; that is to say, it does not necessarily have to be designed as a Web component. It can take any form, as long as it supports the SOAP standard.

Apache Axis also provides a set of libraries that allow you to create Web services clients. We will use these libraries to create a command line program which will call our Sales Web service.

Before we begin our client code, it should be pointed out that writing a Web services client is not a trivial task. You would normally take the WSDL descriptor file for the Web service you wish to contact and feed it into a specific language-based tool, which would then give you a determinate language skeleton to work with, since WSDL is not intended to be read or interpreted by humans directly.

Axis does offers this mechanism, as do many other SOAP tools, but this would present another set of configuration tasks for us which would divert us from our main purpose. Since our Web service is not that complex, we can create a client from scratch without the need of any special tools. This would not be the case for an elaborate Web service.

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

import javax.xml.rpc.ParameterMode;

public class Customer
{
 public static void main(String [] args) throws Exception {

 // We will be invoking our compiled Web service
 // as detailed in the WSDD file
 String endpoint = "http://localhost/axis/services/Sales";

 // You could also invoke the non-compiled Web service
 // at the following location:
 // String endpoint = "http://localhost/axis/Sales.jws";

 // Check the input
 if (args == null || args.length != 2) {
  System.err.println("Usage : 
                       Customer lowestprice highestprice");
  return;
 }

 Integer i1 = new Integer(args[0]);
 Integer i2 = new Integer(args[1]);

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

 // Prepare the call for the Web service
 call.setTargetEndpointAddress( new java.net.URL(endpoint) );
 call.setOperationName("onsale");
 call.addParameter( "op1",XMLType.XSD_INT,ParameterMode.IN );
 call.addParameter( "op2",XMLType.XSD_INT,ParameterMode.IN );
 call.setReturnType( XMLType.XSD_STRING );

 // Make the actual call and assign the answer to a String
 String ret = (String) call.invoke( new Object [] { i1, i2 });

 // Print the obtained result
 System.out.println("Our current sales : " + ret);
   }
}


The Web service client first imports the necessary classes from the Axis libraries, which are included in the Axis JAR files that have been used throughout this article. Immediately after declaring our main Java method we define a String that takes the deployment location of our Web service. Notice that we can call either our source-code Web service or our compiled version.

Prior to initiating our call to the Web service, we check the parameters provided by the user at run-time to assure an appropriate invocation. The rest of the code is fairly self-explanatory, with the Call class taking up the majority of the workload. It is this class invoke() method that actually makes the invocation and assigns its corresponding answer to a String, which is later printed to the console.

Using this client you can obtain an answer from your recently deployed Web service based on the input and ranges you provide.

You have just deployed an end to end Web service using Axis -- congratulations!

In close, Web services discovery

The steps we just took represent the typical procedure you would follow when designing your own Web services, with the exception of one more issue -- Web services discovery.

In our example we knew beforehand where our Web service was deployed and what its exact functionality was. When this is not the case, an extra Web services layer is needed. We can assure that potential users or business partners can locate our service by placing it in a central repository that also tells what our Web service does and where it is located. A UDDI (Universal Description, Discovery, and Integration) directory is such a place. Other discovery mechanisms available include IBM's recent standardized Web Services Inspection Language and the older ebXML standard.

We have covered the sufficient ground to allow you to deploy your ow Web services, but for now we will leave exploring these discovery issues as well as other Web services Clients and languages for future articles.


Originally published January 2004 [ Publisher Link ]

Back to Article List