Aaron Johnson Now with 50% less caffeine!

Posted
31 August 2005 @ 10am

Tagged
J2EE, Open Source, SOAP

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.


10 Comments

Posted by
Franck
6 September 2005 @ 4pm

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


Posted by
Jay
18 September 2005 @ 8pm

This should be on Axis website!!! Thanks!


Posted by
Siva
21 September 2005 @ 11pm

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


Posted by
Rakesh
21 November 2005 @ 6pm

Hi Aaron,

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

Thanks

Rakesh


Posted by
Manjunath Jf
2 January 2006 @ 6am

Hi aaron,

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

Regards,
Manjunath J


Posted by
mohan
13 January 2006 @ 4am

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


Posted by
asma
1 February 2006 @ 1pm

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…


Posted by
Suzanne
15 February 2007 @ 8am

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


Posted by
Shuying
23 March 2008 @ 3am

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?


Posted by
Manish kumar Agrahari
5 October 2008 @ 10pm

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…


Leave a Comment

Links: 8-30-2005 Update to embedded Axis application in Tomcat