Sie sind auf Seite 1von 8

c 


      

IBM has given a lot of code to the Apache group, including SOAP4J, their group of SOAP
tools. The Apache SOAP and SOAP4J guys got together and are working on the latest and
greatest tool set called Apache AXIS, which features not only better performance, but also
some new features that make it trivial to play in this new world. I see the most common
actions being "I want to expose this functionality as a Web service," and "I want to access
that Web service." Surely it should be very straight-forward to strap on this interface, and
you shouldn't have to learn everything there is to know about the underlying platform. This is
the same idea as not having to know about the IP and TCP layer when accessing a URL over
HTTP. Let's keep it simple, folks.

In this article, I will show two parts of this new system:

1.?u First, I will show the "easy to deploy" feature that lets you drop a source file into the
AXIS Web application and have it become a Web service -- just like that!
2.?u Then we will use the new WSDL2Java and Java2WSDL tools to see how we can
quickly get a WSDL descriptor and access the associated Web service, and then how
to easily expose some Java code.

è c  


   


The Apache guys realized that it would be really nice to be able to drop some code
somewhere and have it become a Web service "just like that." This simplicity is a current
trend; Microsoft has it in .NET, and BEA in the WebLogic 7 platform. But just how easy is it
to:

1.?u Deploy a piece of code?


2.?u Write a client that accesses the Web service?
3.?u Obtain the WSDL for the deployed Web service?

Deploy a Java Class as a Web service

Let's take the simple Calculator.java class from the samples.userguide.example2 package
and expose its two methods (add() and subtract()) through Web services. We simply copy
the Java file into the Axis Web application, using the extension .jws instead of .java:

% cp samples\usersguide\example2\Calculator.java
%TOMCAT_HOME%\webapps\axis\Calculator.jws

Just by having the code (with the .jws extension) in the Web application deploys it and allows
us to access it. If we open a browser and access the file (e.g.
http://localhost:8080/axis/Calculator.jws) we will be told that we are talking to a Web
service. How easy was that?! A simple copy command and we are done.

Write a Client That Accesses the Web Service

Now we have a deployed Web service; we need to access it. Let's look at a client that allows
us to pass in a math operation (add or subtract) and the two amounts to work with.

package samples.userguide.example2;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;

import org.apache.axis.encoding.XMLType;

import org.apache.axis.utils.Options;

import javax.xml.rpc.ParameterMode;

public class CalcClient {

public static void main(String [] args) throws Exception {

Options options = new Options(args);

String endpoint = "http://localhost:" + options.getPort() +

"/axis/Calculator.jws";

// Do argument checking

args = options.getRemainingArgs();

if (args == null || args.length != 3) {

System.err.println("Usage: CalcClient <add|subtract arg1 arg2");

return;

String method = args[0];

if (!(method.equals("add") || method.equals("subtract"))) {

System.err.println("Usage: CalcClient <add|subtract arg1 arg2");

return;

// Make the call

Integer i1 = new Integer(args[1]);

Integer i2 = new Integer(args[2]);

Service service = new Service();

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

call.setTargetEndpointAddress(new java.net.URL(endpoint));

call.setOperationName( method );
call.addParameter("op1", XMLType.XSD_INT, ParameterMode.PARAM_MODE_IN);

call.addParameter("op2", XMLType.XSD_INT, ParameterMode.PARAM_MODE_IN);

call.setReturnType(XMLType.XSD_INT);

Integer ret = (Integer) call.invoke( new Object [] { i1, i2 });

System.out.println("Got result : " + ret);

The code first imports all of the required classes. Then we set the URL of the Web service that
we want to invoke. Skip past the argument checking, and we get to the meat: we configure
the method that we want to call, the parameters to pass, and then invoke the service itself.
So, we have deployed and accessed the Web service by writing a minimal amount of code.

Let's walk through the following process:

1.?1. We have a piece of code that calculates the Fibonacci sequence for a given
iteration.
2.?2. We want to take the existing code, wrap it up as a Web service, and then deploy it
to the Apache Axis system.
3.?3. 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:

1.?1. View: Take a peek at the existing Fibonacci code.


2.?2. Java2WSDL: Generate the WSDL file for the given Fibonacci interface.
3.?3. WSDL2Java: Generate the server side wrapper code, and stubs for easy client
access.
4.?4. FibonacciSoapBindingImpl: Fill in wrapper to call the existing Fibonacci code.
5.?5. Deploy: Deploy the service to Apache Axis.
6.?6 . 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:

1.?u Name of output WSDL (fib.wsdl)


2.?u URL of the Web service (http://localhost:8080/axis/services/fibonacci)
3.?u Target namespace for the WSDL (urn:fibonacci)
4.?u Map Java package = namespace (fibonacci = urn:fibonacci)
5.?u 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:

1.?u Base output directory (.)


2.?u Scope of deployment (Application, Request, or Session)
3.?u 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)
4.?u Package to place code (fibonacci.ws)
5.?u 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:

1.?u 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.
2.?u Fibonacci.java: This is a remote interface to the Fibonacci system (extends Remote,
and methods from the original Fibonacci.java throw RemoteExceptions).
3.?u FibonacciService.java: Service interface of the Web services. The ServiceLocator
implements this interface.
4.?u FibonacciServiceLocator.java: Helper factory for retrieving a handle to the service.
5.?u FibonacciSoapBindingSkeleton.java: Server-side skeleton code.
6.?u FibonacciSoapBindingStub.java: Client-side stub code that encapsulates client
access.
7.?u deploy.wsdd: Deployment descriptor that we pass to the Axis system to deploy
these Web services.
8.?u 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));

Das könnte Ihnen auch gefallen