Embeddding an Apache Axis application in Tomcat

One of the applications I’ve been heading up at my 8-to-5 needed a SOAP API that fronted a Java application deployed on Tomcat. If you’ve spent any time with Axis you know that it’s not the simplest thing to deal with; in fact it’s downright complex if you want do anything more than the simplest thing using SOAP. The simplest? Write your source code, rename the .java file to have a .jws extension and then copy the file into a public directory inside your servlet container (see ‘Deploy a Java Class as a Web Service’). Easy. But this method leaves alot to be desired: you can’t use packages in the source code and the code is compiled at runtime which means you don’t find out about compilation errors until after deployment (one way around this would be to first compile the .java file to make sure that it works and then use Ant to copy / rename the .java file to a .jws) and you can’t specify custom type mappings, among other things. Lucky for you, the jws method isn’t the only way you can do it.

The next two options give you flexibility with the additional cost of complexity. The first method is well covered in the documentation: Axis comes packaged with a web application that you can deploy to your servlet container and then add your custom services using a remote administration client also provided with the war file that you deploy. The downside (at least in my environment) is that this means you now have to maintain and deploy two separate applications: my Java based web application would be deployed to Tomcat and then the same business logic would be deployed to the Axis engine running inside of Tomcat. I felt that it would be simpler to maintain to instead deploy the web application and the SOAP application together as one application in one war file. That of course, is not well documented (in fact other than a PDF file that’s part of the ‘Java Development with Ant‘ written by Erik Hatcher, there is no mention of deploying your web application alongside an Axis application without using the Axis AdminClient). Hence the article you’re reading now.

step 1: setup application / dependent libraries: I’ll make the assumption that you already have a web application that you want to expose SOAP webservices with which means you probably have a file structure that looks like something like this:

index.jsp
  - WEB-INF
    web.xml
    -classes
    -lib

You’ll need to add the following libraries to your WEB-INF/lib directory:
* axis.jar
* axis-ant.jar
* jaxrpc.jar
* wsdl4j.jar
* commons-logging.jar
* commons-discovery.jar
* saaj.jar

If you don’t, you can download the sample application I wrote that exposes a single hello world webservice.

Alright, so either you’ve downloaded the sample application or you’ve got your own application and you’ve added the above libraries to your WEB-INF/lib directory. Now you’re ready to write some script to expose your existing classes.

step 2: use WSDL2Java / Java2WSDL to generate the server side wrapper & deployment descriptors for the classes you want to expose. Write a interface:

package net.cephas.soap;
public interface HelloWorld extends java.rmi.Remote {
  public java.lang.String sayHello(java.lang.String in0)
    throws java.rmi.RemoteException;
}

and then a corresponding implementation which should be named $InterfaceName + SoapBindingImpl

package net.cephas.soap;
import java.rmi.RemoteException;
public class HelloworldSoapBindingImpl implements HelloWorld {
  public String sayHello(String name) throws RemoteException {
    return "hello " + name;
  }
}

Next, you can use Ant (but you could easily run this from the command line as well) to create the WSDL and generate the server side wrapper & deployment descriptors. You’ll need to define two tasks in Ant:

<taskdef name="axis-java2wsdl" classname="org.apache.axis.tools.ant.wsdl.Java2WsdlAntTask">
  <classpath refid="compile.classpath" />
</taskdef>
<taskdef name="axis-wsdl2java" classname="org.apache.axis.tools.ant.wsdl.Wsdl2javaAntTask">
  <classpath refid="compile.classpath" />
</taskdef>

and then you can generate the WSDL:

<axis-java2wsdl
  classname="net.cephas.soap.HelloWorld"
 style="rpc"
  namespace="urn:soap.cephas.net"
  location="http://localhost:8080/${project.distname}/soap/helloworld"
  output="${basedir}\generated\helloworld.wsdl">
</axis-java2wsdl>

and generate the server side wrappers:

<axis-wsdl2java
  output="${basedir}\generated"
  serverside="true"
  skeletondeploy="true"
  url="${basedir}\generated\helloworld.wsdl"
  verbose="true"
  debug="true">
</axis-wsdl2java>

Copy the generated web service deployment descriptor (deploy.wsdd) file to WEB-INF/server-config.wsdd:

<copy file="generated/net/cephas/soap/deploy.wsdd"
  tofile="WEB-INF/server-config.wsdd" />

and the *SoapBindingSkeleton.java file to your source tree:

<copy todir="src/net/cephas/soap" includeEmptyDirs="no">
  <fileset dir="generated/net/cephas/soap">
    <patternset>
    <include name="*SoapBindingSkeleton.java" />
    </patternset>
    </fileset>
</copy>

Finally, compile your source and either jar it up to the WEB-INF/lib directory or deploy the compiled classes to the WEB-INF/classes directory.

step 3: configure web.xml with the appropriate servlet mappings. The last thing you need to do is to map a resource path in your application to Axis, you accomplish this by adding a servlet and servlet-mapping element to your web.xml:

<servlet>
  <servlet-name>AxisServlet</servlet-name>
  <display-name>Apache-Axis Servlet</display-name>
  <servlet-class>
    org.apache.axis.transport.http.AxisServlet
  </servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>AxisServlet</servlet-name>
  <url-pattern>/soap/*</url-pattern>
</servlet-mapping>

You can see that I’ve selected ‘/soap/’ as the resource path which in combination with the server-config.wsdd means that I’ll invoke the SOAP web service using a URL like this:

/embeddedaxis/soap/helloworld?wsdl

where embeddedaxis is the name I’ve the sample application. It will probably be different for your application.

Phew! That’s an awful lot of scripting and configuration to deploy hello world, but at least now you don’t have to rely on .jws files or deploying your application separately from the SOAP service. If you’re trying to do the same thing and something you read above doesn’t make sense, ping me.

Download embeddedaxis.zip.

This entry was posted in J2EE, Open Source, SOAP. Bookmark the permalink.

12 Responses to Embeddding an Apache Axis application in Tomcat

  1. Franck says:

    Good job, Aaron.

    I faced the same problems about 3 months ago and I’d have liked to read your article at that time…
    I had to deploy in both Tomcat (for development/unit testing) and Weblogic 8.1 SP3.
    Weblogic comes bundled with an older version of SAAJ Api wich Axis doesn’t quite like (had to put Axis’ saaj.jar in first place in Weblogic’ classpath in order to make it work).

    To sum up my experience, Axis is a headache for the beginner who doesn’t want to use the simple but very restrictive ‘JWS’ deployment approach.

    Thanks for your work,

    Franck

  2. Jay says:

    This should be on Axis website!!! Thanks!

  3. Siva says:

    Did you get a chance to look at the features of the Web Tools Project(WTP) Plugin for Eclipse 3. It is pretty decent in generating test jsp and code against a wsdl

  4. Rakesh says:

    Hi Aaron,

    you have just helped me enormously!!! The Apache Axis docs are seriously lacking what you have provided.

    Thanks

    Rakesh

  5. Manjunath Jf says:

    Hi aaron,

    Its a very good example for the beginers too. Thank you very much.

    Regards,
    Manjunath J

  6. mohan says:

    hi aaron,
    That is wonderfull but can i know how is it possible to implement the same using axis c++ ?

  7. asma says:

    Hey !

    Thanx a bunch…u just helped me and my totally tired group mates understand within minutes what would have taken us hours if we started reading those axis docs….

    And by the way please try to explain the steps about Ant and build.xml etc more clearly!
    they need some improvement…

  8. Suzanne says:

    If the java2wsdl throws a classnotfound exception for your class (ie HelloWorld), make sure you have the classpath argument in java2wsdl set. :)

  9. Shuying says:

    Hey, guy, very clear, thank you very much:)
    Here I also get a question for ya: Do you know how to make an Eclipse Plugins exposed as Web Services using Axis?

  10. Manish kumar Agrahari says:

    Hey !

    Thanx a bunch…u just helped me and my totally tired group mates understand within minutes what would have taken us hours if we started reading those axis docs….

    And by the way please try to explain the steps about Ant and build.xml etc more clearly!
    they need some improvement…

  11. muppasani says:

    Thanks for the comprehensive example

  12. Benoit says:

    Hey ,
    I used Axis a long time ago and I needed good axis doc to start again using it.
    I need to use Axis 1 for some of its “deprecated” feature (rpc/encoded) and your tutorial is great.
    It brings new info instead of just copying Axis web site content. And it is working

    A little note : in axis wsdl2java taskdef, url must supply the protocol (file://) otherwise the ant script fails

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>