Apache Axis

Apache Axis is a JAX-RPC-compliant open source SOAP engine implementation from ASF (Apache Software Foundation). It typically runs as a Web application within a Web container like Apache Tomcat. This deployment allows it to benefit from Web container features like resource poolng, multi-threading, HTTP protocol handling, security support, and so on.

At the time of writing this chapter, the latest binary release of Axis is axis-1.1RC2. This is what we use, along with Web container software Apache Tomcat 4.1.18, the one we used in Chapter 9, Web Application Security. Although these specific releases have been used to develop and test the examples, they should work fine with future releases as well.

Rest of the chapter assumes that you have Tomcat installed on your machine.

Installing and Running Axis

Download the zip file containing the runtime binaries by following the download instructions available at the Axis homepage at http://ws.apache.org/axis. For Axis-1.1RC2, name of the distribution zip file is axis-1_1rc2.zip. At the end of the download, you should have this file in your working directory. To unzip it, open a command shell and issue the following command:

C:apache>jar xvf axis-1_1rc2.zip
						

This creates the Axis home directory, axis-1_1RC2, in the current directory. Set environment variable AXIS_HOME to point to this directory. We refer to it for running the example programs.

Look inside this directory. Here you will find Axis documentation within the docs directory, jar files within the lib directory, sample applications within the samples directory and the Axis Web application, packaged within a directory tree rooted at axis, within the webapps directory. If you are new to Axis then spend some time going through the documentation.

To deploy Axis to Tomcat, create file axis.xml in the webapps subdirectory of the Tomcat home directory. The content of this file is shown below:

<Context path="/axis" docBase="c:\apache\axis-1_1RC2\webapps\axis"
        debug="0" privileged="false">
</Context>

You should change the value of docBase to use the pathname of the Axis installation directory on your machine. An alternative deployment mechanism is to copy the Axis Web application directory tree rooted at axis to the webapps directory of the Tomcat home directory.

Now change your working directory to Tomcat home directory and start Tomcat:

C:apachejakarta-tomcat-4.1.18-LE-jdk14>binstartup
						

Once Tomcat is running, you can check for successful deployment of Axis by pointing your Web browser to http://localhost:8080/axis. Recall that the Tomcat listens for HTTP connections at port 8080 by default. If your installation is configured for a different port then you should use that port in the URL.

Successful Axis deployment is confirmed if your browser displays the Axis welcome page as shown in Figure 11-2.

Figure 11-2. Axis Welcome Page.


Clicking the Validate link brings up a configuration report page with a host of information on jar files in the CLASSPATH, system properties, Web container identification and so on. During development, this page is helpful in identifying configuration problems. However, it reveals too much information about the system and could be a security risk. Hence, it is advised that you disable this particular page in production systems by editing the web.xml file of Axis Web application.

You can view the currently deployed Web services by clicking the View link. The resulting page not only lists the deployed Web services by name but also includes available operations and the URL to retrieve corresponding WSDL documents. Again, this capability should be disabled on production systems.

A Simple Web Service

In this section, we develop a simple Web service, deploy it, and write a client program to access it. This Web service accepts a String object as input and returns the same String as output. The basic motivation is to become comfortable using Axis and build a base example that can be extended to illustrate security concepts later on.

Though there are many different ways to develop a Web service with Axis, we start with a Java class StringEchoService1. The source file StringEchoService1.java is shown below and its electronic copy, along with other source files and execution scripts, can be found in subdirectory srcjsbookch11ex1 of the JSTK installation directory:

// File: srcjsbookch11ex1StringEchoService1.java
public class StringEchoService1 {
    public String echo(String arg){
        return arg;
    }
}

You may wonder: What is special about this class that makes it fit for being a Web service? Nothing! All the magic is in the Axis runtime system that takes this class and provides the necessary plumbing for WSDL generation, conversion of request documents into Java String object, invocation of the method, and so on. Of course, this works only for simple classes that follow certain rules. Refer to Axis documentation for more details.

To deploy this Web service, you need to first compile the source file and place the compiled file, or a jar file containing this file, in a location from where Axis Web application can load it. For a compiled class file, the location is axisWEB-INFclasses directory and for a jar file, the location is axisWEB-INFlib directory, within the webapps directory of Tomcat installation directory. Assuming that the environment variable AXIS_HOME is set to the Axis home directory, carry out these steps by issuing commands:

C:ch11ex1>javac StringEchoService1.java
C:ch11ex1>jar cf ex1.jar StringEchoService1.class
C:ch11ex1>copy ex1.jar %AXIS_HOME%webappsaxisWEB-INFlib
						

The above sequence of commands compiles the StringEchoService1.java file, archives the compiled class file into the jar file ex1.jar and copies this file to the lib directory of the Axis Web application.

Once this is done, we need to deploy the Web service. This requires running Axis utility org.apache.axis.client.AdminClient with a deployment descriptor file deploy.wsdd as argument. To be able to run this utility, Tomcat should be running with Axis deployed, and you should have all the jar files of directory %AXIS_HOME%lib in the CLASSPATH. Also, do not forget to restart the Tomcat after copying the ex1.jar to the lib directory of the Axis Web application.

The deployment descriptor file deploy.wsdd is shown below in Listing 11-1.

Listing 11-1. Deployment descriptor for example Web service
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
           xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

 <service name="StringEchoPort1" provider="java:RPC">
  <parameter name="wsdlTargetNamespace"
    value="http://www.pankaj-k.net/jsbook/examples/"/>
  <parameter name="wsdlServiceElement" value="StringEchoService1"/>
  <parameter name="wsdlServicePort" value="StringEchoPort1"/>
  <parameter name="wsdlPortType" value="StringEcho"/>
  <parameter name="scope" value="session"/>
  <parameter name="className" value="StringEchoService1"/>
  <parameter name="allowedMethods" value="*"/>
 </service>
</deployment>

Note that this deployment descriptor specifies the target namespace URI for WSDL as "http://www.pankaj-k.net/jsbook/examples/", the port name as "StringEchoPort1", the service name as "StringEchoService1" and the implementation class as "StringEchoService1". We need these values to write a client program for this service. Parameter "allowedMethods" is used to control which methods of the class should be exposed through WSDL. A value of “*” implies that all methods are exposed. Refer to Axis documentation for a detailed description of all parameters.

To deploy the Web service, run the AdminClient class with deployment descriptor file as argument. The class AdminClient is part of the Axis jar files. To be able to run it, you must set the CLASSPATH to include all the jar files in the %AXIS_HOME%lib directory. This is accomplished by running the following sequence of commands:

C:ch11ex1>set _CP=.
C:ch11ex1>for %f in (%AXIS_HOME%lib*) do call cpappend.bat %f
C:ch11ex1>set CLASSPATH=%_CP%;%CLASSPATH%
						

Here, the batch file cpappend.bat contains the command "set _CP=%_CP%;%1". The use of this file helps to get all the jar files of the directory %AXIS_HOME%lib in the CLASSPATH without individually listing each of the files. This flexibility is useful as the names and the number of jar files sometimes change from one release to another.

We are now ready to run the AdminClient program:

C:ch11ex1>java org.apache.axis.client.AdminClient deploy.wsdd
- Processing file deploy.wsdd
- <Admin>Done processing</Admin>

You can check for successful deployment by pointing your Web browser to the Axis welcome page and clicking on the View link to list the deployed Web services. You should find StringEchoPort1 service there. If you get an error, try listing the services after stopping and starting the Tomcat. Once you see the StringEchoPort1 in the list of deployed services, you know that the deployment has been successful.

A Web service deployment survives Web container stop and start, meaning a restart of the Web container doesn't mean that all the deployed services get undeployed.

To view the WSDL description of the deployed service, point your Web browser to http://localhost:8080/axis/services/StringEchoPort1?wsdl. The browser displays the WSDL document generated by Axis. This WSDL file is shown in Listing 11-2.

Listing 11-2. WSDL document of Web service StringEchoService1
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
        targetNamespace="http://www.pankaj-k.net/jsbook/examples/"
        xmlns:impl="http://www.pankaj-k.net/jsbook/examples/"
        xmlns:intf="http://www.pankaj-k.net/jsbook/examples/"
        xmlns:apachesoap="http://xml.apache.org/xml-soap"
        xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
        xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:message name="echoResponse">
    <wsdl:part name="echoReturn" type="xsd:string"/>
  </wsdl:message>
  <wsdl:message name="echoRequest">
    <wsdl:part name="in0" type="xsd:string"/>
  </wsdl:message>
  <wsdl:portType name="StringEcho">
    <wsdl:operation name="echo" parameterOrder="in0">
      <wsdl:input name="echoRequest" message="impl:echoRequest"/>
      <wsdl:output name="echoResponse" message="impl:echoResponse"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="StringEchoPort1SoapBinding"
         type="impl:StringEcho">
    <wsdlsoap:binding style="rpc"
           transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="echo">
      <wsdlsoap:operation soapAction=""/>
      <wsdl:input name="echoRequest">
        <wsdlsoap:body use="encoded"
              encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
              namespace="http://www.pankaj-k.net/jsbook/examples/"/>
      </wsdl:input>
      <wsdl:output name="echoResponse">
        <wsdlsoap:body use="encoded"
              encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
              namespace="http://www.pankaj-k.net/jsbook/examples/"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="StringEchoService1">
    <wsdl:port name="StringEchoPort1"
            binding="impl:StringEchoPort1SoapBinding">
      <wsdlsoap:address
       location="http://localhost:8080/axis/services/StringEchoPort1"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Can you figure out where all these values came from? Axis got some of them from the deployment descriptor file deploy.wsdd and figured out others by introspecting the implementation class StringEchoService1.

You can undeploy the Web service by running the AdminClient with name of the file with XML text instructing Axis to undeploy the StringEchoPort1 Web service:

C:...ex1>java org.apache.axis.client.AdminClient undeploy.wsdd
- Processing file undeploy.wsdd
- <Admin>Done processing</Admin>

File undeploy.wsdd contains the XML document identifying the service to be undeployed:

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

This operation simply instructs Axis to not to process request messages directed to the Web service but it doesn't remove the ex1.jar file from the lib directory.

A Web Service Client

The next step is to write a client program to invoke the StringEchoPort1 Web service. We use JAX-RPC DII (Dynamic Invocation Interface) for this purpose. This interface includes low-level APIs to get the WSDL document, form the request message, send it and receive the response message, as shown in Listing 11-3.

Listing 11-3. Source File EchoClient.java
// File: srcjsbookch11ex1EchoClient.java
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.Service;
import javax.xml.rpc.Call;

public class EchoClient{
  public static void main(String [] args) throws Exception {
    String epAddr =
        "http://localhost:8080/axis/services/StringEchoPort1";
    String wsdlAddr = epAddr + "?wsdl";
							String nameSpaceUri = "http://www.pankaj-k.net/jsbook/examples/";
    String svcName = "StringEchoService1";
    String portName = "StringEchoPort1";

    java.net.URL wsdlUrl = new java.net.URL(wsdlAddr);
    ServiceFactory svcFactory = ServiceFactory.newInstance();
    QName svcQName = new QName(nameSpaceUri, svcName);
    Service svc = svcFactory.createService(wsdlUrl, svcQName);

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

    call.setTargetEndpointAddress(epAddr);
    call.setOperationName( new QName(nameSpaceUri, "echo") );
    call.setPortTypeName( new QName(nameSpaceUri, portName) );

    Object arg = "Hi, How are you?";
    System.out.println("sending: " + arg );
    String res = (String) call.invoke(new Object[] {arg});
    System.out.println("received: " + res );
  }
}

Note the use of the service endpoint address, the WSDL location address, the WSDL namespace URI, the service name, the port name and the method name in constructing and initializing an instance of javax.xml.rpc.Call object. For actual invocation, you call the method invoke() on this object, passing an Object array, initialized with the method arguments. For details of JAX-RPC classes and methods used in Listing 11-3, refer to the Axis API Javadocs.

The client program is compiled and runs like any normal Java program, with the environment variable CLASSPATH set so that it includes Axis jar files:

C:ch11ex1>javac EchoClient.java
C:ch11ex1>java EchoClient
sending: Hi, How are you?
received: Hi, How are you?

Congratulations! You have successfully deployed and accessed your first Web service.

You may have noticed that the client source code is much more complex than the service code. Actually, there are other, simpler ways to write clients using generated stubs and/or dynamic proxies. However, we chose to use the relatively low-level dynamic invocation interface, for only this interface gives us the power we need to extend this example later in the chapter to perform some of the security-related tasks.

Watching the SOAP Messages

Although our client and service programs are using Java objects as input and output, internally these Java objects are being converted to SOAP messages and being exchanged over an HTTP connection. You could use tcpmon, a nifty, Swing-based GUI tool packaged with the Axis, to intercept SOAP messages and look at them. The only requirement is that the client program be modified to target all the outbound messages to a port that this tool is configured to listen to. Also, the tool needs to be configured to forward the message to the address of the Web service.

To run tcpmon with the listen port of 8079 and forward port of 8080 on the local machine, first set the CLASSPATH to include all Axis jars and then issue the command:

C:ch11ex1>java org.apache.axis.utils.tcpmon 8079 localhost 8080
						

This brings up a graphical window, ready to display connections and messages that come to port 8079. After display, all these connections and messages are forwarded to port 8080. The next step is to change the port number in service endpoint address from 8080 to 8079 in EchoClient.java, compile it and run it in a separate command window. You should see something like Figure 11-3. Although it doesn't show the complete SOAP request and response, you can figure out that the method argument is passed as a text node within the SOAP Body element and so is the return value. This tool comes quite handy for analyzing what happens under the hood!

Figure 11-3. Watching SOAP Request and Response with tcpmon.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.118.40