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.