Axis: The next generation of Apache SOAP

Apache takes its SOAP implementation to new heights

Over the past couple of years, the Simple Object Access Protocol (SOAP) has taken off at rocket speed. A solid understanding of SOAP concepts has become essential for any strong software professional, especially software architects. The reason is quite simple. SOAP provides the foundation for one of the most exciting developments in the software industry today: Web services. Web services are exciting because they take application integration and interoperability to a new level never possible before, even with Java and J2EE (Java 2 Platform, Enterprise Edition).

To summarize, SOAP offers the following:

  1. An XML-based wire protocol, which is thus Web/firewall friendly
  2. A universally accepted W3C (World Wide Web Consortium) standard backed by all major and minor market players, including Microsoft, Sun Microsystems, IBM, and HP

Before diving into this article, you might want to review my previous JavaWorld series, "Clean Up Your Wire Protocol with SOAP," where I explain the basics of SOAP and why it proves so critical to the future of distributed computing:

In those articles, I focused on how developers could use Apache SOAP to build SOAP-based projects. Since then, Apache has completely rebuilt its SOAP implementation, creating a new project called Axis. In this article, I provide a high-level overview of the improvements Axis targets. I also show how to create and deploy a simple Web service with Axis.

What is Axis?

All software developers understand the importance of software toolkits; they prove essential to ensuring high developer productivity in this era of rapid application development. Coding with SOAP is no different. Although you could handcraft all your XML-based SOAP messages, you would probably want to use a SOAP toolkit to speed your development. After all, you don't handcode all your RPC (remote procedure call) messages in bits and bytes; why should SOAP messages be any different?

One such toolkit is available for SOAP. Apache SOAP's first generation was based on SOAP4J, IBM's donated codebase. I covered this excellent implementation in Parts 2 through 4 of my earlier series. As good as it was, Apache SOAP is now better. Axis is not just a rewrite of Apache SOAP, but a complete re-architecture. For Axis, Apache plans two alpha releases with partial functionality, a beta release with complete functionality, and a final release, Axis 3.0, which will supersede Apache SOAP 2.2. Alpha 1 was released in August 2001 and alpha 2 was released in September 2001. Though alpha 3 was issued in December 2001, this article focuses on the alpha 2 release (which features the same functionality as alpha 3).

When complete, Axis will:

  1. Support SOAP 1.1, just as Apache SOAP 2.2 does. For example, Axis will completely support the SOAP concept of mustUnderstand headers. Axis's final release will have a few SOAP 1.2 features as well as partial support for pluggable XML protocols.
  2. Likely prove much faster and more resource efficient than Apache SOAP, since it uses SAX (Simple API for XML) instead of DOM (Document Object Model). SAX allows lazy parsing of XML documents, which in many cases is more efficient -- especially when the entire XML document does not need to be parsed or kept in memory for long time periods.
  3. Have a clean and simple abstraction for designing transports -- i.e., senders and listeners for SOAP over various protocols such as SMTP (Simple Mail Transfer Protocol), FTP, message-oriented middleware, and so on. Also, the engine's core will be completely transport independent.
  4. Automatically generate WSDL (Web Services Description Language) from deployed services. The Axis alpha 2 version also comes with the wsdl2java tool for building Java proxies and skeletons from WSDL documents. Thus, you not only get the WSDL for an Axis-deployed service, but you can also build stubs and skeletons from the WSDL for extremely easy client code development. Note that the WSDL that feeds into the wsdl2java tool can originate from any source as long as it adheres to the WSDL specification. I'll show you an example of using this feature later.
  5. Support EJB (Enterprise JavaBeans) deployment as services. This resembles a feature provided by some application servers, such as BEA WebLogic Server.
  6. Feature improved deployment support and the ability to drop Java files into a deployment directory and expose the classes as services. I'll show you an example of this later.
  7. Better interoperate with Microsoft's SOAP implementation and .Net services. Over the past year, Apache and Microsoft have undergone several iterations of their SOAP implementations; with each iteration, they become more interoperable with each other. For details, see the summary of the last Apache/Microsoft interoperability meeting.

Although I use the future tense in the bullet points above, the alpha 2 release already includes many of these features.

Now, let's install Axis and create a simple service with it.

Install Axis

Although the Axis installation guide is fairly straightforward, these instructions will further ease the process:

First, ensure you have a Web server installed. I use Tomcat. If you have another Web server, you can still download Tomcat's latest version (version 4.0.1, at the time of this publication) from http://jakarta.apache.org/tomcat/index.html. Unzip the downloaded zip file into your C drive, or your preferred drive. (Note that I refer to the C drive in all my instructions.) You should see Tomcat installed in the directory C:\jakarta-tomcat-4.0.1 (if you have a different version, substitute your version number in place of 4.0.1). I will refer to this directory as TOMCAT_HOME.

Second, download Axis's latest release from http://xml.apache.org/axis/index.html. Unzip this zip file into your C drive as well. Axis should now be installed in the directory C:\axis-1_0 (for version 1.0, alpha 2). I will refer to this directory as AXIS_HOME.

Third, copy the Axis folder from AXIS_HOME\webapps into TOMCAT_HOME\webapps.

Now copy xerces.jar from your Xerces installation into the TOMCAT_HOME\webapps\axis\WEB-INF\lib directory. If you don't have Xerces, you can download it for free from http://xml.apache.org/xerces2-j/index.html. All you have to do is download the zip file and unzip it into your C drive. xerces.jar will be in the root of your Xerces installation -- for example, C:\xerces-1_4_4.

Finally, set up a context in the server.xml file in the directory TOMCAT_HOME\conf by adding this line:

<Context path="/axis" docBase="axis" debug="0" reloadable="true"/>

That's it. Axis is now installed and ready to use.

Create the Web service

Like the service in "Clean Up Your Wire Protocol with SOAP, Part 2," the Web service that we will create here is the "Hello World" of Web services. As you can see below, it is a class that has one method, sayHelloTo(), which takes a name as its only parameter and returns a customized hello message. Note that the class is not littered with any Axis-specific code:

public class HelloServer 
{
    public String sayHelloTo(String name)
    {
      System.out.println("sayHelloTo(String name)");
      return "Hello " + name + ", How are you doing?";       
    }
}

Deploy the Web service the easy way

To deploy this Hello World Web service, just copy and paste the HelloServer.java file into the TOMCAT_HOME\webapps\ directory and change its extension from .java to .jws. That's all there is to it; the Web service is deployed and ready for use. And you didn't even have to compile the Java file! This is Axis feature number 6 (described above) in action.

When a client invokes a service deployed in this manner, Axis will automatically locate the file, compile the class, and convert SOAP calls correctly into your service class's Java invocations. As you will see in the next section, the service name corresponds to the name of the .jws file. The magic that allows the Web server to invoke the Axis engine (i.e., servlet) when a .jws file is requested is located in the TOMCAT_HOME\webapps\axis\WEB-INF directory. This file's appropriate section is shown below:

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

Based on the above configuration information, whenever Tomcat -- or any J2EE-compliant Web server -- encounters a .jws file in the Axis context (set up above during installation), it will invoke the AxisServlet. The AxisServlet then performs its magic as described above.

Create the client

Now let's create a simple client that we'll use to test the service. The code to do that is shown here:

package javaworld.axis;
import org.apache.axis.client.ServiceClient;
public class Client1
{
      public static void main(String[] args) throws Exception 
      {      
                String endpoint = "http://localhost:8080/axis/HelloServer.jws";
        
            ServiceClient client = new ServiceClient(endpoint);
            String ret = (String)client.invoke("","sayHelloTo",new Object [] {args[0]});
            System.out.println(ret);
      }   
}

As with Apache SOAP, the client code is a bit more involved than the server code. But it is much simpler than the equivalent Apache SOAP client code, which is also shown below for reference. To understand the code below, please refer to "Clean Up Your Wire Protocol with SOAP, Part 2."

package javaworld.axis
import java.net.URL;
import java.util.Vector;            
import org.apache.soap.SOAPException;
import org.apache.soap.Constants;
import org.apache.soap.Fault;
import org.apache.soap.rpc.Call;
import org.apache.soap.rpc.Parameter;
import org.apache.soap.rpc.Response;
                             
public class Client
{
   public static void main(String[] args) throws Exception 
   {      
         URL url = new URL("http://localhost:8080/apache-soap/servlet/rpcrouter");         
         String name = args[0];
         
         // Build the call.
         Call call = new Call();
         call.setTargetObjectURI("urn:Hello");
         call.setMethodName("sayHelloTo");
         call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);         
         Vector params = new Vector();         
         params.addElement(new Parameter("name", String.class, name, null));
         call.setParams(params);
         // Invoke the call.
         Response resp = null;         
         try
         {
            resp = call.invoke(url, "");
         }
         catch( SOAPException e )
         {
            System.err.println("Caught SOAPException (" + e.getFaultCode() + "): " + e.getMessage());
            System.exit(-1);
         }
   
         // Check the response.
         if( !resp.generatedFault() )
         {
            Parameter ret = resp.getReturnValue();
            Object value = ret.getValue();            
            System.out.println(value);
         }
         else
         {
            Fault fault = resp.getFault();            
            System.err.println("Generated fault: ");
            System.out.println ("  Fault Code   = " + fault.getFaultCode());  
            System.out.println ("  Fault String = " + fault.getFaultString());
         }
      }
      catch(Exception e)
      {
         e.printStackTrace();
      }
   }   
}

It should be obvious that Axis does a much better job shielding the client developer from the details. In the simplest case (as the one in this article), you need to create only an instance of the class org.apache.axis.client.ServiceClient, which requires the service endpoint as its constructor parameter. The endpoint here is http://localhost:8080/axis/HelloServer.jws, since (1) the Web server is on the same machine as the client; (2) Tomcat by default listens for HTTP requests on port 8080; and (3) the service is deployed as HelloServer.jws. Finally, you invoke any method on the service by simply calling the invoke() method on the ServiceClient instance. At the very least, invoke() requires both the method's name on the service to invoke, and an Object array of parameters.

Test the service

To test the service, begin by compiling the client using the following command sequence. Note that axis.jar must be included in the CLASSPATH to successfully compile the client application:

set CLASSPATH=AXIS_HOME\lib\axis.jar
javac Client1.java

Start Tomcat if it's not already started. To start Tomcat, run the startup.bat batch file located in TOMCAT_HOME\bin\. Next, run the client application:

set CLASSPATH=C:\dev\;AXIS_HOME\lib\axis.jar;AXIS_HOME\lib\log4j-core.jar
java javaworld.axis.Client1 John

This time, in addition to axis.jar, you must also include log4j-core.jar, which is the jar file that contains classes used by axis.jar's classes for logging. Also, C:\dev is the directory containing the javaworld package, so you must include it in the CLASSPATH too.

Deploy the Web service the flexible way

Deploying the Web service as a .jws file works for simple services such as the one in this article. However, this approach fails to meet most commercial Web services' flexibility requirements, such as the ability to specify custom type mappings or create handler chains. Instead, most deployments will probably use deployment files such as the one shown below for our Web service:

1 2 Page
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more