第9章

Webサービスコンシューマの生成

この章では、Webサービスコンシューマ(Webサービスにアクセスするプログラム)を生成する「Webサービスウィザード」の使用について、基本手順と一般的なシナリオを説明します。トピックは次のとおりです。

For more information    Webサービスを作成する場合のウィザードの使用手順とシナリオについては、を参照してください。

 
Top of page

基本

Novell exteNd Director 開発環境のWebサービスウィザードを使用すると、Javaベースのコンシューマプログラムに必要なコードを生成し、標準(SOAPベース)のWebサービスにアクセスすることができます。生成されたコードでは、背後で行われるすべてのHTTP SOAP処理を取り扱い、コンシューマプログラムでWebサービスを「Javaリモートオブジェクト」(RMIを使用)として呼び出したり、そのメソッドを呼び出したりできるようにします。

入力する際、ウィザードでは、アクセスするWebサービスを説明するWSDLファイルが必要です。このファイルでは、次のようなさまざまなWebサービスの実装を処理できます。

ウィザードでは、JAX-RPC (Java API for XML-based RPC)およびNovell exteNd Web Services SDK (Novell exteNdに含まれているJAX-RPX実装)に基づいて、Javaソースファイルを生成します。JAX-RPCは、Webサービスサポートを提供するJ2EE仕様です。

生成されたファイルは、そのまま使用したり、必要に応じて変更したりできます。このJava指向の方法には、低レベルのSOAP APIをコーディングする代わりに、熟知しているRMIおよびJ2EEの技術を使用してWebサービスを処理できるという利点があります。

For more information    Webサービスの概念、標準、および技術の紹介については、を参照してください。

For more information    ウィザードについて詳しくは、を参照してください。

 
Top of page

手順

コンシューマプログラムの開発プロセスには、次の作業が含まれます。

  1. プロジェクトのセットアップによる生成の準備

  2. ウィザードによりコンシューマコードを生成するWebサービスを説明するWSDLファイルの提供

  3. ウィザードの使用によるコンシューマファイルの生成

  4. 次に対するJavaソースを含む、ウィザードが作成する生成されたファイルの検査

  5. 実行するメソッド呼び出しおよび参照先Webサービスの場所を調整するための、生成されたファイルの編集

  6. そのままの状態、または他のJavaアプリケーションにコンシューマコードを含むことによる、生成されたファイルの使用

  7. 開発環境(テスト用)および運用環境でのコンシューマプログラムの実行

 
Top of page

生成の準備

Webサービスウィザードの使用を準備するには、次の操作を行います。

  1. exteNd Director 開発環境で適切なプロジェクトをセットアップします。

    作成するプロジェクトのタイプは、ウィザードによって生成されるコンシューマコードの最終的な使用方法により異なります。例を次に示します。

    コンシューマコードの使用場所

    作成するプロジェクト

    標準のJavaアプリケーション(おそらくウィザードによって生成する単純なJavaクライアントクラスに基づく)

    JARプロジェクト

    J2EEアプリケーションクライアント

    CARプロジェクト

    JSPページまたはサーブレット

    WARプロジェクト

    Enterprise JavaBean

    EJB JARプロジェクト

  2. 次に示すWebサービスSDK に必要なアーカイブを、プロジェクトに追加します。

    これらのJARは、Novell exteNd tools\compilelibディレクトリにあります。

  3. 生成、編集された後でコンシューマクラスをコンパイルできるように、プロジェクトのクラスパスを編集します。次のアーカイブを含める必要があります。

J2EEプロジェクトには、j2ee_api_1_n.jar (J2EEプロジェクトを作成するとexteNd Director 開発環境に自動的に含まれます)も必要です。

 
Top of page

WSDLファイルの提供

コンシューマコードを生成するには、ターゲットWebサービスを説明するWSDLファイルをWeb Service Wizardに提供する必要があります。ウィザードを開始する前に、このWSDLファイルの場所またはURLを取得しておくことが推奨されます。

一般的なシナリオは次のとおりです。

 
Top of section

例:Autoloan .NET WebサービスのWSDLファイル

コンシューマコードを生成して、EMI (Equated Monthly Instalment) Calculatorという名前でXMethodsパブリックレジストリに一覧表示されているAutoloan .NET Webサービスを使用するとします。このWebサービスでは、特定の期間(月数)における毎月の返済額、利率、およびローン金額が計算され返されます。

この場合、www.xmethods.netというWebサイトにアクセスすると、対応する次のWSDLファイルのURLを見つけることができます。

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

このURLを提供すると、WebサービスウィザードではWSDKファイルを読み込み、Autoloan Webサービスについて必要な情報を取得します。

  <?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

WSDLの概要

Autoloan WSDLでは、HttpGetおよびHttpPostの定義(message、portType、binding、およびservice portを含む)を無視できます。Soapの定義のみ、開発しているWebサービスコンシューマプログラムに適用されます。

このWebサービスでは、calculate()という1つのメソッドが表示されています。このメソッドは、3つのdouble (Months、RateOfInterest、およびAmount)を含むCalculateオブジェクトを取得し、1つのString (CalculateResult)を含むCalculateResponseオブジェクトを返します。Webサービスウィザードでは、このメソッドの呼び出しをサポートするために、対応するリモートインタフェースをJavaで生成します。

typesセクションは、CalculateおよびCalculateResponseのXMLスキーマ定義を指定します。Webサービスウィザードでは、これらのオブジェクトを表現するために、対応するタイプクラスをJavaで生成します。

AutoloanSoapのbindingセクションを参照すると、このWebサービスがRPCスタイルではなく、ドキュメントスタイルとして定義されていることが確認できます。これは、.NET Webサービスで一般的に見られます。バインドスタイルは、SOAPメッセージの形式を説明します。また、他のWebサービス環境との相互運用性に影響を与える場合があります。

バインドスタイル

説明

ドキュメント(リテラル使用)

SOAPメッセージの本文には、交換されるXMLドキュメントのみが含まれ、メッセージ部分は、WSDLファイルのXMLスキーマでリテラルとして定義された要素にマップされます。

RPC (エンコード使用)

SOAPメッセージの本文には、指定のエンコードルールを各メッセージパートのタイプに適用することによって受信者が解釈しなければならないアドホック要素に個別ラップされた、引数および戻り値が含まれます。

Webサービスウィザードでは、指定のバインドスタイルの処理に必要なJavaコードを生成します。

AutoloanSoapのport定義(WSDLファイルの最後)は、Webサービスにアクセスできる場所のアドレス(URL)を指定します(次を参照)。

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

Webサービスウィザードでは、Webサービスを呼び出すために生成するサービスクラスおよびスタブクラスでこのURLを使用します。

 
Top of page

コンシューマファイルの生成

プロジェクトをセットアップして、適切なWSDLファイルを見つけたら、Web Service Wizardを使用する準備が整ったことになります。ウィザードでは一度に1つのWebサービスコンシューマが作成されるため、複数を開発する場合は、Webサービスコンシューマを複数回使用する必要があります。

ウィザードを起動するたびに、WSDLファイルおよび指定した他の入力が使用され、1セットのコンシューマソースファイルが生成されます。このプロセスの要約は次のとおりです。

  1. [ファイル]>[新規作成]の順に選択して[新規ファイル]ダイアログボックスを表示し、[Webサービス]タブに移動します。

  2. [既存のWebサービス]を選択して、Webサービスウィザードを起動します。

  3. プロジェクトの場所についての情報を入力するようウィザードで要求されたら、次の項目を指定します。

    たとえば、Autoloan Webサービスのコンシューマを生成するとします。この場合、ターゲットJARプロジェクトとしてWebServiceConsumerSampleを指定し、生成されたクラスのパッケージとしてcom.exsamp.netを指定できます。

    GWSCprojloc

  4. ウィザードの指示に従って、ターゲットWebサービスを説明するWSDLファイルを指定します。

    たとえば、Autoloan Webサービスのコンシューマを生成する場合は、XMethodsパブリックレジストリから取得したWSDLファイルのURLを指定します。

    GWSCwsdl

  5. クラス生成およびSOAPオプションを入力するようウィザードで要求されたら、作成するコードについての詳細を指定する必要があります。

    たとえば、これらのオプションによって、Autoloan Webサービスの適切なコンシューマソースファイル(タイプクラスを含む)が生成されます。

    GWSCoptions

    注記:   jBroker Web 1.xアプリケーションのサポートは、旧製品との互換性のオプションを使用して有効にできます。詳細については、(前の章の)jBroker Web 1.xとの互換性を選択した場合を参照してください。

  6. Webサービスコンシューマのオプション指定が終了したら、[完了]をクリックします。

 
Top of page

生成されたファイルの検査

ウィザードを終了すると、Webサービスコンシューマに対して指定したものがすべて生成され、プロジェクトの他の部分は、サポートする変更内容で更新されます。

ウィザードによって生成されるもの

詳細

リモートインタフェースのJavaソースファイル

xxx.java    java.rmi.Remoteを拡張し、ターゲットWebサービス(WSDLファイルから決定)によって表示されるメソッドを宣言するインタフェース。生成されたスタブクラスのxxx_Stubは、Webサービスのメソッド呼び出しをサポートするためにこのインタフェースを実装します。

スタブのJavaソースファイル

xxxService.java    ターゲットWebサービスのスタブを取得するためにJAX-RPCクライアントによって使用されるサービスインタフェース。

xxxServiceImpl.java    スタブ(xxx_Stub)のインスタンス化を処理するサービス実装クラス。ダイナミック(スタブレス)呼び出しを含む、ターゲットWebサービスにアクセスする他の方法もサポートしています。

サービスインタフェースおよび実装クラスに対して生成される名前は、WSDLによって異なり、Serviceというテキストが省略される場合もあります。

xxx_Stub.java    JavaベースのコンシューマからターゲットWebサービスへのメソッド呼び出しを容易にします。xxx_Stubは、各メソッド呼び出しに対して適切なHTTP SOAP要求を送信することによって生成されたリモートインタフェースを実装します。

xxxClient.java    ターゲットWebサービスのコンシューマとして機能する単純なクライアントアプリケーション。(サービスオブジェクトを通じて)スタブを取得した後、そのスタブを使用してWebサービスのメソッドを呼び出します。

xxxClientは、exteNd Director 開発環境から([ツール]>[Webサービスクライアントクラスの実行]の順に選択)、またはコマンドラインから実行できます。

プロジェクトコンテンツへの更新

ウィザードによりプロジェクトが更新され、生成されたファイルがそのプロジェクトに追加されます。

 
Top of section

生成されたファイル名について

ファイル名を生成する場合、Webサービスウィザードでは、JAX-RPCによって指定された名前付けルールに従います。Webサービスコンシューマでは、結果として付けられるファイル名は、WSDL内の定義に基づきます。

簡単にするため、このマニュアルでは、WSDL定義から派生して生成されたWebサービスコンシューマのファイル名の一部を表すのにxxxを使用します。

 
Top of section

生成の追加情報

Webサービスウィザードでは、Webサービスコンシューマのファイル(前のリストを参照)を生成する際に、背後でWebサービスSDKコンパイラを使用します。場合によっては、次のようなアプリケーションに固有の要件をサポートするために、これらのコンパイラによって追加コードやファイルが生成されることがあります。

For more information    詳細については、Web Services SDKヘルプを参照してください。

 
Top of section

例:Autoloan .NET Webサービスの生成されたコンシューマファイル

Autoloan Webサービスに対してWebサービスウィザードにより生成されたコンシューマコードは、次のWebサービスアクセスの標準ファイルから構成されます。

また、WSDLで定義された次の複雑なタイプをマップするためのアプリケーション固有のファイルから構成されます。

これらのファイルは、作成すると、指定したディレクトリパスにあるプロジェクトにウィザードによって追加されます。

GWSCoutput

 
Top of page

生成されたファイルの編集

Webサービスウィザードによって生成されたファイルを編集する場合は、次のガイドラインに従います。

ガイドライン

詳細

編集する必要のあるファイル

  • xxxClient.java

編集してはいけないファイル

  • xxxService.java

  • xxxServiceImpl.java

  • xxx_Stub.java

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

 
Top of section

xxxClient.javaファイルの編集

生成されたxxxClient.javaファイルを使用する前に、次のことを確認してください。

process()メソッド

process()メソッドでは、生成されたクライアントアプリケーションによってWebサービスのメソッドが呼び出されます。ここでは、生成されたリモートインタフェースで定義された各メソッドを呼び出して、コンソールに戻り値を表示する、コメント付きのコードを示します。たとえば次のように使います。

  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(com.exsamp.net.Calculate));
  
  }

このコードは、次のように変更する必要があります。

  1. 実行する1つまたは複数のメソッド呼び出しのコメントを解除します。

  2. ハードコード化された値またはランタイム時に提供されるパラメータとして、各メソッド呼び出しに適切な引数を提供します。ランタイム引数には、指定された値を検証するコードを追加することもできます。

  3. 戻りデータタイプをチェックし、toString()を使用して変換できることを確認します。toString()を使用して変換できない場合は、System.out.printlnに代わるものを使用して、返されたデータを表示します。

編集後のcalculate()メソッド呼び出しの行は、次のようになります。

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

getRemote()メソッド

この節では、getRemote()メソッドの基本的な使用方法、およびバインド情報を指定する必要がある場合のgetRemote()メソッドの修正方法について説明します。

基本的な使用方法   getRemote()メソッドでは、Webサービスへのメソッド呼び出しを処理するために、生成されたクライアントアプリケーションによってリモートオブジェクトが取得されます。このリモートオブジェクトは、生成されたスタブクラス(xxx_Stub)のインスタンスです。スタブインスタンスを作成するために、getRemote()では次のことが実行されます。

  1. JNDI検索を通じて、(サービスインタフェースxxxServiceおよび実装クラスxxxServiceImplの)サービスオブジェクトをインスタンス化します。

  2. スタブを取得するためにサービスオブジェクトによって(サービスインタフェースで)提供されるメソッドを呼び出します。

getRemote()に対して生成された一般的なコードの例は、次のようになります。通常は、このコードを編集する必要はありません。

  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;
  }

バインド情報の指定   ウィザードにより、ターゲットWebサービスのバインド情報が、生成されたスタブクラス(xxx_Stub.java)およびサービス実装クラス(xxxServiceImpl.java)に含まれます。バインドでは、Webサービスにアクセスできる場所の「サービスエンドポイントアドレス」が提供されます。WSDLファイルでは、このアドレスは、soap:address location要素のURLです。

別の方法として、getRemote()メソッドでスタブインスタンスを作成する際に、使用するバインドを指定することもできます。この方法を使用すると、(Webサービスが新しい場所に移動した場合などに)スタブクラスのバインドを無効にできます。スタブのアドレスプロパティを設定するために、次のように1行のコードを追加するだけで、これを実行できます。

  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

生成されたファイルの使用

この時点でのWebサービスコンシューマコードの使用方法は、開発しているアプリケーションの性質によって異なります。たとえば、場合によっては、生成されたxxxClient.javaファイルを強化してアプリケーションに含める必要があったり、xxxClient.javaから独自のクラスに構文をコピーすることだけが必要になったりします。しかし、いずれの場合でも、生成されたリモートインタフェース、サービス、およびスタブファイルが常に必要となります。

アプリケーション固有のコード化を開始する前に、基本的なxxxClientをテストして、コンシューマコードが期待どおりに機能することを確認しておくことを推奨します。まず、ソースファイルをコンパイルするためにプロジェクトを作成する必要があります。その後、次の節で説明するように、xxxClientを実行できます。

 
Top of page

コンシューマプログラムの実行

生成されたWebサービスコンシューマプログラムであるxxxClientは、標準のJavaアプリケーションです。このプログラムは、次のいずれかの方法で実行できます。

 
Top of section

開発環境から

生成されたクライアントをすばやく簡単にテストできるようにするために、exteNd Director 開発環境にはWeb Service Wizard Client Runnerが装備されています。この機能によって、現在のプロジェクトのクライアントアプリケーションがリストされ、実行するクライアントアプリケーションを選択できます。クライアントアプリケーションを実行するたびに、必要なファイルをすべて含むようにクラスパスが自動的に設定され、コマンドライン引数を指定できるようになります。

Procedure Client Runnerを使用する

  1. 実行するコンパイル済みのクライアントクラスを含む「プロジェクト」を開きます。

  2. [ツール]>[Webサービスクライアントクラスの実行]の順に選択して、[クライアントランナー]ウィンドウを表示します。

  3. [実行するクライアントクラス]ドロップダウンからクライアントを選択します。

    このドロップダウンには、プロジェクト内の、main()メソッドを持つコンパイルされたクラスが表示されます。

  4. 次を希望する場合は、[コマンドラインを表示する]をオンにします。

  5. クライアントに必要なコマンドライン引数を入力します(各引数は、スペースを使用して区切ります)。

  6. [実行]をクリックしてクライアントを実行し、ウィンドウのディスプレイコンソール部分で出力を確認します。

たとえば、生成されたAutoloanSoapClientクラスをClient Runnerを使用して実行すると、次のようになります。

GWSCrunner

AutoloanSoapClientが実行されると、Autoloan Webサービスのcalculate()メソッドが呼び出され、ローンデータ(期間、率、金額)を含むCalculateオブジェクトが渡されます。calculate()メソッドは、支払い情報の文字列を含むCalculateResponseオブジェクトを返します(これは、AutoloanSoapClientによって画面に表示されます)。

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

 
Top of section

コマンドラインから

生成されたクライアントは、オペレーティングシステムのコマンドプロンプトから実行することもできます。この場合、必要なファイル(生成されたコンシューマクラス、wssdk.jarなど)をすべて含むようにクラスパスを設定する必要があります。

クライアントのコマンドラインを表示してコピーするには、Web Service Wizard Client Runnerを使用する方法が推奨されます(前の節の説明を参照)。その後、コマンドラインをコマンドプロンプトに貼り付けて実行できます。

クライアントを他のコンピュータ(開発コンピュータ以外)で実行する場合は、このコマンドラインにリストされるすべてのファイルにアクセスできることを確認してください。



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