
Creating Web Services with Apache Axis
Pages: 1, 2
Obtain the WSDL For the Deployed Web Service
What if we wanted to retrieve a WSDL file to give to a programmer
who needs to talk to our particular service (and who may be using .NET
or Python or something else to access it)? Once again, the Apache folk
thought of this. We can grab the definition file simply by accessing
the Web service and appending?WSDL to the end of the URL. If I simply point my browser to http://localhost:8080/axis/Calculator.jws?WSDL, I get the XML descriptor sent back to me.
Working With a Production Web Service
Although it is really easy and convenient to shove our Java code under the Axis directory as a .jws file,
that will not be the way you deploy all of your Web services. A lot of
the time we want more fine-grained control over the Web service, to
tweak it, and to use other more advanced features. Luckily, with other
tools, it is still easy for us to work with our code in a more formal
manner.
Let's walk through the following process:
- We have a piece of code that calculates the Fibonacci sequence for a given iteration.
- We want to take the existing code, wrap it up as a Web service, and then deploy it to the Apache Axis system.
- Once we have a running service on the server side, we will create
Java stubs that allow us to communicate with the service, only
requiring the WSDL.
After going through this full process, you will be able to create
clients to any Web services (when given the WSDL), and wrap up any code, exposing it as a Web service.
Here are the steps we will walk through:
- View: Take a peek at the existing Fibonacci code.
- Java2WSDL: Generate the WSDL file for the given Fibonacci interface.
- WSDL2Java: Generate the server side wrapper code, and stubs for easy client access.
- FibonacciSoapBindingImpl: Fill in wrapper to call the existing Fibonacci code.
- Deploy: Deploy the service to Apache Axis.
- Client: Write a client that uses the generated stubs, to easily access the Web service.
1. View: Take a Peek at the Existing Fibonacci Code
There are two files of our existing code: an interface and an
implementation class. First, we have defined the Fibonacci interface
that has methods for calculating one, or a range of Fibonacci sequences.
Example 1. Fibonacci.java
package fibonacci;
public interface Fibonacci {
// Method to calculate the fibonacci sequence
public int calculateFibonacci( int num );
// Method to return an array of results
public int[] calculateFibonacciRange(int start, int stop);
}
Then we have the real implementation of that code. Don't spend time
studying how the Fibonacci sequence is calculated, though; that isn't
the point.
Example 2. FibonacciImpl.java
package fibonacci;
public class FibonacciImpl {
public int calculateFibonacci( int num ) {
if (num <= 0) return 0;
if (num == 1) return 1;
int previous1 = 1, previous2 = 0, fib = 0;
for (int i=2; i <= num; i++) {
// the fib is the answer of the previous two answers
fib = previous1 + previous2;
// reset the previous values
previous2 = previous1;
previous1 = fib;
}
return fib;
}
public int[] calculateFibonacciRange(int start, int stop) {
int[] results = new int[stop + 1];
for (int x=start; x <= stop; x++) {
results[x] = this.calculateFibonacci( x );
}
return results;
}
}
2. Java2WSDL: Generate the WSDL File For the Given Fibonacci Interface
Now we have the Fibonacci code, and we compile it (javac ). Here comes the first tool that helps us out as we endeavor to make that code a Web service. The Java2WSDL
command line will generate a standard WSDL file that conforms to a
given interface. We tell the program the information it needs to know
as it builds the file, such as:
- Name of output WSDL (
fib.wsdl )
- URL of the Web service (http://localhost:8080/axis/services/fibonacci)
- Target namespace for the WSDL (
urn:fibonacci )
- Map Java package = namespace (
fibonacci = urn:fibonacci )
- Fully qualified class itself (
fibonacci.Fibonacci )
The full command for our example becomes something like:
% java org.apache.axis.wsdl.Java2WSDL -o fib.wsdl
-l"http://localhost:8080/axis/services/fibonacci" -n urn:fibonacci
-p"fibonacci" urn:fibonacci fibonacci.Fibonacci
After the program runs, we see that a new file, fib.wsdl,
was created for us. If we look inside the file, we see 114 lines of
information that needed to be created for this Web service. Aren't you
glad that you didn't need to write the whole thing? How do people write
them by hand?
Now we have defined our Web service.
3. WSDL2Java: Generate the Server-side Wrapper Code and Stubs For Easy Client Access
Our next step is to take this WSDL and generate all of the glue code
for deploying the service, as well as stubs for accessing it. The
WSDL2Java tool comes to our aid here to take that chore out of our
hands.
Let's generate this code into the fibonacci.ws package,
to keep it separate from the original code. Once again, we need to tell
this command line some information so it can go ahead and do its work:
- Base output directory (.)
- Scope of deployment (Application, Request, or Session)
- Turn on server-side generation (we wouldn't do this if we were
accessing an external Web service, as we would then just need the
client stub)
- Package to place code (
fibonacci.ws )
- Name of WSDL file (
fib.wsdl )
The full command for our example becomes something like:
% java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -p fibonacci.ws fib.wsdl
After running this program, a slew of code has been generated for us in the fibonacci\ws directory:
FibonacciSoapBindingImpl.java : This is the implementation code for our Web service. This is the one file we will need to edit, tying it to our existing FibonacciImpl .
Fibonacci.java : This is a remote interface to the Fibonacci system (extends Remote , and methods from the original Fibonacci.java throw RemoteExceptions ).
FibonacciService.java : Service interface of the Web services. The ServiceLocator implements this interface.
FibonacciServiceLocator.java : Helper factory for retrieving a handle to the service.
FibonacciSoapBindingSkeleton.java : Server-side skeleton code.
FibonacciSoapBindingStub.java : Client-side stub code that encapsulates client access.
deploy.wsdd : Deployment descriptor that we pass to the Axis system to deploy these Web services.
undeploy.wsdd : Deployment descriptor that will undeploy the Web services from the Axis system.
4. FibonacciSoapBindingImpl: Fill-in Wrapper to Call the Existing Fibonacci Code
We need to tweak one of the output source files to tie the Web service to FibonacciImpl.java . FibonacciSoapBindingImpl.java is waiting for us to add the stuff into the methods that it created. The lines that we added are in bold:
package fibonacci.ws;
import fibonacci.FibonacciImpl;
public class FibonacciSoapBindingImpl implements fibonacci.ws.Fibonacci {
FibonacciImpl fib = new FibonacciImpl();
public int calculateFibonacci(int in0) throws java.rmi.RemoteException {
return fib.calculateFibonacci(in0);
}
public int[] calculateFibonacciRange(int in0, int in1) throws java.rmi.RemoteException {
return fib.calculateFibonacciRange(in0, in1);
}
}
We are simply tying in to the existing class. We could have
hard-coded the methods in this class, but in the real world, we
probably want to wrap logic as Web services, and not just enable access via that interface.
5. Deploy: Deploy the Service to Apache Axis
Now we are ready to deploy this service. We have to do the following:
- Compile the Service Code:
We first have to javac fibonacci\ws\*.java
- Package the code for Axis to find:
Next, we package all of the code that we have and copy it into Axis' classpath:
% jar cvf fib.jar fibonacci/*.class fibonacci/ws/*.class
% mv fib.jar %TOMCAT_HOME%/webapps/axis/WEB-INF/lib
- Deploy the Web Service using the WSDD Deployment Descriptor:
Apache Axis has an Admin client command line tool that we can
use to do tasks such as (un)deployment, and listing the current
deployments. We pass the deployment descriptor to this program so it
can do its work:
% java org.apache.axis.client.AdminClient deploy.wsdd
<admin>Done processing</admin>
Now our Fibonacci Web service is alive and running in the server!
6. Client: Write a Client That Uses the Generated Stubs to Easily Access the Web Service
We should check to see if it is working, right? Let's write a simple
client that uses the generated client code from the WSDL2Java step, to
calculate the Fibonacci number at the 10th step.
All we need to do in the code is to get access to the service via the ServiceLocator ,
and then call methods on the remote handle that we have to the service.
It looks just like normal Java; none of that silly SOAP or RPC code is
in sight. Isn't that nicer? (Take another look at the CalcClient that we used at the beginning, and compare it to this code.)
package fibonacci;
public class FibonacciTester {
public static void main(String [] args) throws Exception {
// Make a service
fibonacci.ws.FibonacciService service =
new fibonacci.ws.FibonacciServiceLocator();
// Now use the service to get a stub to the service
fibonacci.ws.Fibonacci fib = service.getFibonacci();
// Make the actual call
System.out.println("Fibonacci(10) = " +
fib.calculateFibonacci(10));
}
}
Ahh, much nicer.
Conclusion
We have seen that it is much simpler to work with Web services when
using nice tools such as the open source Apache Axis toolkit. Web
services should be easy, and they are finally becoming that way. Take
another look at the steps that we went through, and notice how little
code we wrote to expose our original code as a Web service. These tools
are only going to get better; at some point we will just think, "I want
this as a Web service," and it will happen.
Dion Almaer
is a Principal Technologist for The Middleware Company, and Chief Architect of TheServerSide.Com
J2EE Community.
Return to ONJava.com.


|