Utility Tools

CHAPTER 9

Generating Web Service Consumers

This chapter walks you through the basic steps and a typical scenario for using the Web Service Wizard to generate a Web Service consumer (a program that accesses a Web Service). Topics include:

For more information    To learn about the steps and scenarios for using the wizard when you want to create a Web Service, see Generating Web Services.

 
Top of page

Basics

You can use the Web Service Wizard of the Novell exteNd Director development environment to generate the code needed for a Java-based consumer program to access any standard (SOAP-based) Web Service. The generated code handles all HTTP SOAP processing under the covers, enabling the consumer program to call the Web Service as a Java remote object (using RMI) and invoke its methods.

For input, the wizard requires a WSDL file that describes the Web Service to access. It can handle a wide variety of Web Service implementations, including:

The wizard generates Java source files based on JAX-RPC (Java API for XML-based RPC) and the Novell exteNd Web Services SDK (the JAX-RPC implementation included with Novell exteNd). JAX-RPC is the J2EE specification that provides Web Service support.

You can use the generated files as is or modify them when necessary. The advantage of this Java-oriented approach is that you can deal with Web Services using the familiar technologies of RMI and J2EE instead of coding lower-level SOAP APIs.

For more information    For an introduction to Web Service concepts, standards, and technologies, see Web Service Basics.

For more information    For detailed documentation on the wizard, see Web Service Wizard.

 
Top of page

Steps

The process of developing your consumer program involves:

  1. Preparing to generate by setting up your project

  2. Providing a WSDL file that describes the Web Service for which you want the wizard to generate consumer code

  3. Generating the consumer files by using the wizard

  4. Examining the generated files that the wizard creates, including Java source for:

  5. Editing the generated files to adjust the method calls to make and the Web Service location to point to

  6. Using the generated files either as is or by including the consumer code in some other Java application

  7. Running the consumer program in your development environment (for testing) and in the production environment

 
Top of page

Preparing to generate

To prepare for using the Web Service Wizard, you:

  1. Set up an appropriate project in the exteNd Director development environment.

    The type of project you should create depends on how you ultimately plan to use the consumer code that the wizard will generate. For instance:

    If you plan to use the consumer code in

    You should create

    A standard Java application (perhaps based on the simple Java client class that the wizard generates)

    A JAR project

    A J2EE application client

    A CAR project

    A JSP page or servlet

    A WAR project

    An Enterprise JavaBean

    An EJB JAR project

  2. Add the archives required by the Web Services SDK to your project:

    You'll find these JARs in the Novell exteNd tools\compilelib directory.

  3. Edit the classpath of your project so you can compile your consumer classes once they're generated and edited. You'll need to include:

For J2EE projects, you'll also need j2ee_api_1_n.jar (it's included automatically when you create a J2EE project in the exteNd Director development environment).

 
Top of page

Providing a WSDL file

To generate consumer code, you'll need to provide the Web Service Wizard with a WSDL file that describes the target Web Service. It's a good idea to obtain the file location or URL of this WSDL file before you start the wizard.

These are common scenarios:

 
Top of section

Example: WSDL file for Autoloan .NET Web Service

Suppose you want to generate consumer code to use the Autoloan .NET Web Service, which is listed on the XMethods public registry under the name Equated Monthly Instalment (EMI) Calculator. That Web Service calculates and returns the monthly loan payment for a given term (number of months), interest rate, and loan amount.

In this case, you can go to the Web site www.xmethods.net to discover the URL for the corresponding WSDL file:

  http://upload.eraserver.net/circle24/autoloan.asmx?wsdl

When you provide this URL to the Web Service Wizard, it will read the WSDL file to learn what it needs to know about the Autoloan Web Service:

  <?xml version="1.0" encoding="utf-8"?>
  <definitions xmlns:s="http://www.w3.org/2001/XMLSchema" 
               xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
               xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" 
               xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" 
               xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
               xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
               xmlns:s0="http://circle24.com/webservices/" 
               targetNamespace="http://circle24.com/webservices/" 
               xmlns="http://schemas.xmlsoap.org/wsdl/">
    <types>
      <s:schema attributeFormDefault="qualified" elementFormDefault="qualified" 
                targetNamespace="http://circle24.com/webservices/">
        <s:element name="Calculate">
          <s:complexType>
            <s:sequence>
              <s:element minOccurs="1" maxOccurs="1" name="Months" type="s:double" />
              <s:element minOccurs="1" maxOccurs="1" name="RateOfInterest" type="s:double" />
              <s:element minOccurs="1" maxOccurs="1" name="Amount" type="s:double" />
            </s:sequence>
          </s:complexType>
        </s:element>
        <s:element name="CalculateResponse">
          <s:complexType>
            <s:sequence>
              <s:element minOccurs="1" maxOccurs="1" name="CalculateResult" nillable="true" 
                         type="s:string" />
            </s:sequence>
          </s:complexType>
        </s:element>
        <s:element name="string" nillable="true" type="s:string" />
      </s:schema>
    </types>
    <message name="CalculateSoapIn">
      <part name="parameters" element="s0:Calculate" />
    </message>
    <message name="CalculateSoapOut">
      <part name="parameters" element="s0:CalculateResponse" />
    </message>
    <message name="CalculateHttpGetIn">
      <part name="Months" type="s:string" />
      <part name="RateOfInterest" type="s:string" />
      <part name="Amount" type="s:string" />
    </message>
    <message name="CalculateHttpGetOut">
      <part name="Body" element="s0:string" />
    </message>
    <message name="CalculateHttpPostIn">
      <part name="Months" type="s:string" />
      <part name="RateOfInterest" type="s:string" />
      <part name="Amount" type="s:string" />
    </message>
    <message name="CalculateHttpPostOut">
      <part name="Body" element="s0:string" />
    </message>
    <portType name="AutoloanSoap">
      <operation name="Calculate">
        <input message="s0:CalculateSoapIn" />
        <output message="s0:CalculateSoapOut" />
      </operation>
    </portType>
    <portType name="AutoloanHttpGet">
      <operation name="Calculate">
        <input message="s0:CalculateHttpGetIn" />
        <output message="s0:CalculateHttpGetOut" />
      </operation>
    </portType>
    <portType name="AutoloanHttpPost">
      <operation name="Calculate">
        <input message="s0:CalculateHttpPostIn" />
        <output message="s0:CalculateHttpPostOut" />
      </operation>
    </portType>
    <binding name="AutoloanSoap" type="s0:AutoloanSoap">
      <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
                    style="document" />
      <operation name="Calculate">
        <soap:operation soapAction="http://circle24.com/webservices/Calculate" 
                        style="document" />
        <input>
          <soap:body use="literal" />
        </input>
        <output>
          <soap:body use="literal" />
        </output>
      </operation>
    </binding>
    <binding name="AutoloanHttpGet" type="s0:AutoloanHttpGet">
      <http:binding verb="GET" />
      <operation name="Calculate">
        <http:operation location="/Calculate" />
        <input>
          <http:urlEncoded />
        </input>
        <output>
          <mime:mimeXml part="Body" />
        </output>
      </operation>
    </binding>
    <binding name="AutoloanHttpPost" type="s0:AutoloanHttpPost">
      <http:binding verb="POST" />
      <operation name="Calculate">
        <http:operation location="/Calculate" />
        <input>
          <mime:content type="application/x-www-form-urlencoded" />
        </input>
        <output>
          <mime:mimeXml part="Body" />
        </output>
      </operation>
    </binding>
    <service name="Autoloan">
      <documentation>This Web Service mimics a Simple Autoloan calculator.</documentation>
      <port name="AutoloanSoap" binding="s0:AutoloanSoap">
        <soap:address location="http://upload.eraserver.net/circle24/autoloan.asmx" />
      </port>
      <port name="AutoloanHttpGet" binding="s0:AutoloanHttpGet">
        <http:address location="http://upload.eraserver.net/circle24/autoloan.asmx" />
      </port>
      <port name="AutoloanHttpPost" binding="s0:AutoloanHttpPost">
        <http:address location="http://upload.eraserver.net/circle24/autoloan.asmx" />
      </port>
    </service>
  </definitions>

 
Top of section

Understanding the WSDL

In the Autoloan WSDL, you can ignore the definitions for HttpGet and HttpPost (including message, portType, binding, and service port). Only the Soap definitions apply to the Web Service consumer program you're developing.

Notice that this Web Service exposes one method named calculate(). It takes a Calculate object containing three doubles (Months, RateOfInterest, and Amount) and returns a CalculateResponse object containing one string (CalculateResult). The Web Service Wizard will generate a corresponding remote interface in Java to support calling this method.

The types section specifies the XML Schema definitions for Calculate and CalculateResponse. The Web Service Wizard will generate corresponding type classes in Java to represent these objects.

There's a twist in how those Calculate and CalculateResponse classes will be used in the generated Autoloan consumer code. The Autoloan WSDL happens to follow the wrapper pattern defined by JAX-RPC, which dictates that method parameters in the remote interface should use basic types directly rather than the objects that wrap them. As a result, the calculate() method will be generated to take the three doubles (instead of Calculate) and return the string (instead of CalculateResponse). The wrapping and unwrapping of Calculate and CalculateResponse will be handled under the covers by the generated Autoloan stub class.

If you look in the binding section for AutoloanSoap, you'll see that this Web Service is defined as document style (as opposed to RPC style). That's typical of .NET Web Services. Binding style describes the format of SOAP messages and can affect interoperability with other Web Service environments:

Binding style

What it means

Document (with literal use)

The SOAP message body contains just the XML document being exchanged, and message parts map to elements literally defined in the WSDL file's XML Schema.

RPC (with encoded use)

The SOAP message body contains argument and return values, individually wrapped in ad hoc elements that the recipient must interpret by applying specified encoding rules to each message part's type.

The Web Service Wizard will generate the Java code needed to handle the specified binding style.

The port definition for AutoloanSoap (at the end of the WSDL file) specifies the address (URL) where the Web Service can be accessed:

  http://upload.eraserver.net/circle24/autoloan.asmx

The Web Service Wizard will use this URL in the service and stub classes it generates for calling the Web Service.

 
Top of page

Generating the consumer files

Once you've set up your project and located the appropriate WSDL file, you're ready to use the Web Service Wizard. The wizard produces one Web Service consumer at a time, so you'll need to use it multiple times if you have several to develop.

Each time you launch the wizard, it uses the WSDL file and other input you provide to generate a set of consumer source files. Here's a summary of the process:

  1. Select File>New>File to display the New File dialog and go to the Web Services tab.

  2. Launch the Web Service Wizard by selecting Existing Web Service.

  3. When the wizard prompts you for project location information, specify:

    For example, suppose you're generating a consumer for the Autoloan Web Service. You might specify WebServiceConsumerSample as the target JAR project and com.exsamp.net as the package for generated classes:

    GWSCprojloc

  4. When the wizard prompts you, specify the WSDL file that describes your target Web Service.

    For example, when generating a consumer for the Autoloan Web Service, you specify the WSDL file URL obtained from the XMethods public registry:

    GWSCwsdl

  5. When the wizard prompts you for Web Service type mappings, specify how data types defined in the WSDL (via XML Schema) are to be represented in the generated Java code.

    The default is to create specific Java types for all of the complex XML types in the WSDL. That's usually appropriate and it's the right choice here for the Autoloan Web Service example:

    GWSCtypemap

  6. When the wizard prompts you for class-generation and SOAP options, you must specify details about the code to create:

    For example, these options will generate the appropriate consumer source files for the Autoloan Web Service:

    GWSCoptions

    NOTE:   Support for jBroker Web 1.x applications is available via a backward-compatibility option. For more information, see If you choose jBroker Web 1.x compatibility (in the preceding chapter).

  7. Click Finish when you're done specifying options for the Web Service consumer.

 
Top of page

Examining the generated files

Once you finish the wizard, it generates everything you've specified for your Web Service consumer and updates other parts of your project with supporting changes:

What the wizard generates

Details

Java source file for remote interface

xxx.java    An interface that extends java.rmi.Remote and declares the methods exposed by the target Web Service (as determined from the WSDL file). The generated stub class xxx_Stub implements this interface to support method calls for the Web Service.

Java source files for stubs

xxxService.java    Service interface used by JAX-RPC clients to obtain the stub for the target Web Service.

xxxServiceImpl.java    Service implementation class that handles instantiation of the stub (xxx_Stub). It also supports alternative ways of accessing the target Web Service, including dynamic (stubless) calls.

(Note that the names generated for the service interface and implementation class depend on your WSDL and may omit the text Service.)

xxx_Stub.java    Facilitates method calls from a Java-based consumer to the target Web Service. xxx_Stub implements the generated remote interface by sending an appropriate HTTP SOAP request for each method call.

xxxClient.java    Simple client application that works as a consumer of the target Web Service. It obtains the stub (via the Service object) and then uses the stub to call Web Service methods.

You can run xxxClient from the exteNd Director development environment (select Tools>Run Web Service Client Class) or from a command line.

Updates to project contents

The wizard updates your project to add generated files to it.

 
Top of section

About generated file names

When generating file names, the Web Service Wizard follows the naming rules specified by JAX-RPC. For a Web Service consumer, the resulting file names are based on the definitions in the WSDL.

For simplicity, this documentation uses xxx to represent the portion of a generated Web Service consumer file name that's derived from a WSDL definition.

 
Top of section

Additional details of generation

Under the covers, the Web Service Wizard uses the Web Services SDK compilers when generating the Web Service consumer files listed above. In some cases, these compilers may generate additional code or files to support requirements specific to your application, such as:

For more information    For more information, see the Web Services SDK help.

 
Top of section

Example: generated consumer files for Autoloan .NET Web Service

The consumer code that the Web Service Wizard generates for the Autoloan Web Service consists of these standard files for Web Service access:

And these application-specific files for mapping the complex types defined in the WSDL:

When creating these files, the wizard adds them to your project on the directory path you've specified:

GWSCoutput

 
Top of page

Editing the generated files

Follow these guidelines when editing the files generated by the Web Service Wizard:

Guideline

Details

File you must edit

  • xxxClient.java

Files you should not edit

  • xxxService.java

  • xxxServiceImpl.java

  • xxx_Stub.java

It's OK to edit any of the other generated files, but not typically required.

 
Top of section

Editing the xxxClient.java file

Before using the generated xxxClient.java file, you:

process() method

The process() method is where the generated client application calls methods of the Web Service. Here you'll find commented code for calling each method defined in the generated remote interface and displaying return values on the console. For example:

  public void process(String[] args) throws Exception
  {
      AutoloanSoap remote = getRemote(args);
  
      // The following code has been generated for your testing convenience. In
      // order to successfully test your Web Service, you must uncomment one or
      // more of these lines and supply meaningful arguments where necessary.
      // Once you have modified the test method(s) below, compile this class and
      // execute it from a command line with your class path set appropriately.
  
      // System.out.println("Test Result = " + remote.calculate(double, double, double));
  
  }

You need to modify this code as follows:

  1. Uncomment one or more method calls you want to execute.

  2. Provide appropriate arguments for each method call, either as hardcoded values or as parameters to be furnished at runtime. For runtime arguments, you may also want to add code that validates the values supplied.

  3. Check the return data type to make sure it can be converted using toString(). If not, use an alternative to System.out.println for displaying the data returned.

Here's what the line with the calculate() method call looks like after editing:

  System.out.println("Autoloan Web Service\n  " + 
    "Loan input data:\n    24 months, 8%, $15000\n  " +
    "Output from the Web Service:\n    " +
    remote.calculate(24, 8, 15000));

getRemote() method

This section explains the basic use of the getRemote() method and how to modify it when you need to specify binding information.

Basic use   The getRemote() method is where the generated client application obtains the remote object to handle its method calls to the Web Service. That remote object is an instance of the generated stub class (xxx_Stub). To create the stub instance, getRemote() does the following:

  1. Instantiates the Service object (from the service interface and implementation classes, xxxService and xxxServiceImpl) via JNDI lookup

  2. Calls a method that the Service object provides (in the service interface) to get the stub

Here's an example of the typical code generated for getRemote(). Normally, you don't need to edit it:

  public AutoloanSoap getRemote(String[] args) throws Exception
  {
      InitialContext ctx = new InitialContext();
          
      String lookup = "xmlrpc:soap:com.exsamp.net.Autoloan";
      Autoloan service = (Autoloan)ctx.lookup(lookup);
      AutoloanSoap remote = (AutoloanSoap)service.getAutoloanSoap();
              
      return remote;
  }

Specifying binding information   The wizard includes the binding information for your target Web Service in the generated stub class (xxx_Stub.java) and service implementation class (xxxServiceImpl.java). The binding provides the service endpoint address where the Web Service can be accessed. In a WSDL file, this address is the URL in the soap:address location element.

As an alternative, you can specify the binding to use when creating the stub instance in the getRemote() method. This enables you to override the binding in the stub class (such as when the Web Service has moved to a new location). You just need to add a line of code to set the address property for the stub:

  public AutoloanSoap getRemote(String[] args) throws Exception
  {
      InitialContext ctx = new InitialContext();
          
      String lookup = "xmlrpc:soap:com.exsamp.net.Autoloan";
      Autoloan service = (Autoloan)ctx.lookup(lookup);
      AutoloanSoap remote = (AutoloanSoap)service.getAutoloanSoap();
  
      ((javax.xml.rpc.Stub)remote)._setProperty("javax.xml.rpc.service.endpoint.address",
        "http://upload.eraserver.net/circle24/autoloan.asmx");
  
      return remote;
  }

 
Top of page

Using the generated files

How you use the Web Service consumer code that you have at this point depends on the nature of the application you're developing. Sometimes you might want to enhance the generated xxxClient.java file and include it in your application. At other times you may just copy syntax from xxxClient.java into your own classes. But in either case, you'll always need the generated remote interface, service, and stub files.

Before you start any application-specific coding, it's a good idea to test the basic xxxClient to make sure your consumer code works as expected. You'll first need to build your project to compile the source files. Then you can run xxxClient, as described in the next section.

 
Top of page

Running the consumer program

The generated Web Service consumer program xxxClient is a standard Java application. You can run it in either of these ways:

 
Top of section

From the development environment

To help you test your generated client quickly and easily, the exteNd Director development environment provides the Web Service Wizard Client Runner. This facility lists the client applications in your current project and lets you select one to execute. For each run, it automatically sets the classpath to include all required files and lets you supply command-line arguments.

Procedure To use the Client Runner:

  1. Open the project that contains the compiled client class you want to run.

  2. Select Tools>Run Web Service Client Class to display the Client Runner window.

  3. Select a client from the Client class to run dropdown.

    This dropdown lists every compiled class in your project that has a main() method.

  4. Check Show command line if you want to:

  5. Type any command-line Arguments required by your client (use a space to separate each argument).

  6. Click Run to execute your client and see its output in the display console portion of the window.

For example, here's what it looks like to execute the generated AutoloanSoapClient class using the Client Runner:

GWSCrunner

When AutoloanSoapClient runs, it calls the calculate() method of the Autoloan Web Service and passes a Calculate object containing loan data (term, rate, amount). The calculate() method returns a CalculateResponse object containing a string of payment information, which AutoloanSoapClient displays on the screen:

  Running com.exsamp.net.AutoloanSoapClient...
  *********************
  Autoloan Web Service
    Loan input data:
      24 months, 8%, $15000
    Output from the Web Service:
      Equated Monthly Instalment (EMI) For the Amount $15000 is $678
  *********************

 
Top of section

From a command line

You can also execute the generated client from the command prompt of your operating system. Doing so demands that you set the classpath to include all required files (such as the generated consumer classes, wssdk.jar, and so on).

The recommended approach is to use the Web Service Wizard Client Runner to display and copy the command line for your client (as described in the preceding section). Then you can paste that line to your command prompt and run it.

If you plan to run the client on other computers (beyond your development machine), make sure they have access to all of the files listed in this command line.



Copyright © 2004 Novell, Inc. All rights reserved. Copyright © 1997, 1998, 1999, 2000, 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved.  more ...