Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (日本語) » SQL Anywhere サーバ - プログラミング » SQL Anywhere データ・アクセス API » SQL Anywhere Web サービス

 

チュートリアル:JAX-WS からの Web サービスへのアクセス

次のチュートリアルでは、Java API for XML Web Services (JAX-WS) を使用して Web サービスにアクセスする方法を示します。

チュートリアルを始める前に、Sun から入手可能な JAX-WS ツールが必要です。このパッケージがシステムにインストールされていない場合は、JAX-WS ツールをダウンロードしてインストールしてください。JAX-WS ツールをダウンロードするには、[external link] http://java.sun.com/webservices/ を参照してください。JAX-WS のリンクをクリックすると、[external link] Java API for XML Web Services のページが開きます。Download Now リンクをクリックします。ソフトウェア・パッケージをダウンロードしたら、それをシステムにインストールします。

このサンプルは、JAX-WS 2.1.3 for Windows を使用して開発されました。

JAX-WS からアクセスできる SQL Anywhere SOAP Web サービスは、CONCRETE フォーマットとして宣言する必要があります。

♦  SOAP および DISH サービスを作成するには、次の手順に従います。
  1. コマンド・プロンプトで、次のコマンドを実行して、パーソナル Web サーバを起動します。samples-dir をサンプル・データベースの実際のロケーションと置き換えます。-xs http(port=80) オプションは、HTTP 要求をポート 80 で受け入れるようにデータベース・サーバに指示します。すでにポート 80 で稼働している Web サーバがある場合は、このチュートリアルには 8080 などの別のポート番号を使用し、すべてのポート参照で 80 の代わりに 8080 を使用してください。

    dbeng11 -xs http(port=80) samples-dir\demo.db
  2. Interactive SQL を起動し、DBA として SQL Anywhere サンプル・データベースに接続します。次の文を実行します。

    1. Employees テーブルの一部のカラムをリストするストアド・プロシージャを定義します。

      CREATE PROCEDURE ListEmployees()
      RESULT (
       EmployeeID            INTEGER,
       Surname               CHAR(20),
       GivenName             CHAR(20),
       StartDate             DATE,
       TerminationDate       DATE )
      BEGIN
        SELECT EmployeeID, Surname, GivenName, 
          StartDate, TerminationDate 
        FROM Employees;
      END;
    2. このストアド・プロシージャを呼び出す SOAP サービスを定義します。

      CREATE SERVICE "WS/EmployeeList"
      TYPE 'SOAP'
      FORMAT 'CONCRETE' EXPLICIT OFF
      DATATYPE OUT
      AUTHORIZATION OFF
      SECURE OFF
      USER DBA
      AS CALL ListEmployees();

      EXPLICIT 句は、CONCRETE 型の SOAP または DISH サービスでのみ使用できます。この例の EXPLICIT OFF は、対応する DISH サービスで汎用の SimpleDataset オブジェクトを記述する XML スキーマを生成することを示します。このオプションの影響を受けるのは、生成される WSDL ドキュメントだけです。EXPLICIT ON の使用例は後で紹介します。チュートリアル:JAX-WS でのデータ型の使用を参照してください。

      DATATYPE OUT は、明示的なデータ型情報が XML 結果セットの応答で生成されることを示します。DATATYPE OFF が指定されている場合、すべてのデータは String 型になります。このオプションは、生成される WSDL ドキュメントに影響しません。

      認証はオフになっているため、ユーザ名とパスワードを入力せずにだれでもこのサービスを利用できます。このコマンドは、ユーザが DBA の場合に実行できます。この方法は簡単ですが、安全性に優れていません。

    3. SOAP サービスのプロキシとして機能し、WSDL ドキュメントを生成する DISH サービスを作成します。

      CREATE SERVICE "WSDish"
      TYPE 'DISH'
      FORMAT 'CONCRETE'
      GROUP "WS"
      AUTHORIZATION OFF
      SECURE OFF
      USER DBA;
      

      SOAP サービスと DISH サービスは、CONCRETE フォーマットである必要があります。EmployeeList サービスは WS グループであるため、GROUP 句が含まれます。

  3. DISH サービスにより自動的に生成される WSDL を見てみます。そのためには、Web ブラウザを開き、URL [external link] http://localhost:80/demo/WSDish にアクセスします。DISH は、ブラウザのウィンドウに表示される WSDL ドキュメントを自動生成します。

    特に、SimpleDataset オブジェクトに注目してください。このサービスのフォーマットは CONCRETE で EXPLICIT が OFF になっているため、SimpleDataset オブジェクトは公開されています。この後の手順で、wsimport アプリケーションはこの情報を使用して、このサービス用の SOAP 1.1 クライアント・インタフェースを生成します。

    <s:complexType name="SimpleDataset">
    <s:sequence>
    <s:element name="rowset">
      <s:complexType>
      <s:sequence>
      <s:element name="row" minOccurs="0" maxOccurs="unbounded">
        <s:complexType>
        <s:sequence>
          <s:any minOccurs="0" maxOccurs="unbounded" /> 
        </s:sequence>
        </s:complexType>
      </s:element>
      </s:sequence>
      </s:complexType>
    </s:element>
    </s:sequence>
    </s:complexType>
♦  Web サービス用の JAX-WS インタフェースを生成するには、次の手順に従います。
  1. この例では、Java API for XML Web Services (JAX-WS) と Sun Java 1.6.0 JDK は C: ドライブにインストールされています。JAX-WS バイナリと JDK バイナリがパスに含まれるように PATH 環境変数を設定します。バイナリは次のディレクトリにあります。

    c:\Sun\jaxws-ri\bin
    c:\Sun\SDK\jdk\bin
  2. コマンド・プロンプトで、CLASSPATH 環境変数を設定します。

    SET classpath=.;C:\Sun\jaxws-ri\lib\jaxb-api.jar
    ;C:\Sun\jaxws-ri\lib\jaxws-rt.jar
  3. 次の手順では、Web サービスを呼び出すために必要なインタフェースを生成します。

    同じコマンド・プロンプトで、新しいプロジェクト・ディレクトリを作成し、これを現在のディレクトリにします。このディレクトリで次のコマンドを実行します。

    wsimport -keep -Xendorsed "http://localhost:80/demo/WSDish"

    wsimport ツールは、指定された URL から WSDL ドキュメントを取得し、そのインタフェースを定義する Java ファイルを生成してから、Java ファイルをコンパイルします。

    keep オプションは、.java ファイルを削除しないように wsimport に指示します。このオプションが指定されない場合は、対応する .class ファイルの生成後にこれらのファイルは削除されます。これらのファイルを保存すると、インタフェースの構成の検査が簡単になります。

    Xendorsed オプションは、JAX-WS 2.1 API を JDK6 と一緒に使用できるようにします。

    このコマンドが完了すると、以下の Java ファイルと、各 Java ファイルがコンパイルされた .class ファイルを含む localhost\demo\ws というサブディレクトリ構造が作成されています。

    EmployeeList.java
    EmployeeListResponse.java
    FaultMessage.java
    ObjectFactory.java
    package-info.java
    SimpleDataset.java
    WSDish.java
    WSDishSoapPort.java
♦  生成された JAX-WS インタフェースを使用するには、次の手順に従います。
  1. 次の Java ソース・コードを SASoapDemo.java として保存します。このファイルが、wsimport ツールで生成された localhost サブディレクトリを含むディレクトリと同じ場所にあることを確認してください。

    // SASoapDemo.java illustrates a web service client that
    // calls the WSDish service and prints out the data.
    
    import java.util.*;
    import javax.xml.ws.*;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import localhost.demo.ws.*;
    
    public class SASoapDemo
    {
      @WebServiceRef( wsdlLocation= "http://localhost:8080/demo/WSDish" )
      public static void main( String[] args )
      {
        try {
          WSDish service = new WSDish();
    
          Holder<SimpleDataset> response = new Holder<SimpleDataset>();
          Holder<Integer> sqlcode = new Holder<Integer>();
                
          WSDishSoapPort port = service.getWSDishSoap();
    
          // This is the SOAP service call to EmployeeList
          port.employeeList( response, sqlcode );
    
          localhost.demo.ws.SimpleDataset result = response.value;
          SimpleDataset.Rowset rowset = result.getRowset();
    
          List<SimpleDataset.Rowset.Row> rows = rowset.getRow();
    
          for ( int i = 0; i < rows.size(); i++ ) {
            SimpleDataset.Rowset.Row row = rows.get( i );
            List<Object> cols = row.getAny();
    
            System.out.println( "Number of columns=" + cols.size() );
    
            for ( int j = 0; j < cols.size(); j++ ) {
              // Column data is contained as a SOAPElement
              Element col = (Element)cols.get(j);
              System.out.print(col.getLocalName() + "=" );
              Node node = col.getFirstChild();
              if( node == null ) {
                System.out.println( "(null)" );
              } else {
                System.out.println( node.getNodeValue() );
              }
            }
            System.out.println();
          }
    
        }
        catch (Exception x) {
          x.printStackTrace();
        }
      }
    }

    8080 のように別のポート番号を使用して Web サーバを起動する場合は、import localhost ソース行を次のように変更する必要があります。

    import localhost._8080.demo.ws.*;
  2. SASoapDemo.java をコンパイルします。

    javac SASoapDemo.java
  3. コンパイル済みのクラス・ファイルを実行します。

    java SASoapDemo

    アプリケーションは Web サーバに要求を送信すると、XML 結果セット応答を受け取ります。この応答は、複数のロー・エントリを含むローセットを持つ EmployeeListResult から構成されています。この応答には、クエリの実行結果の sqlcode も含まれています。この応答の例を次に示します。

    <tns:EmployeeListResponse>
     <tns:EmployeeListResult xsi:type='tns:SimpleDataset'>
      <tns:rowset>
        <tns:row>...</tns:row>
    .
    .
    .
        <tns:row>...</tns:row>
       </tns:rowset>
     </tns:EmployeeListResult>
     <tns:sqlcode>0</tns:sqlcode>
    </tns:EmployeeListResponse>

    ローセットの各ローは、次のようなフォーマットで送信されます。

    <tns:row>
       <tns:EmployeeID xsi:type="xsd:int">1751</tns:EmployeeID>
       <tns:Surname xsi:type="xsd:string">Ahmed</tns:Surname>
       <tns:GivenName xsi:type="xsd:string">Alex</tns:GivenName>
       <tns:StartDate xsi:type="xsd:date">1994-07-12-04:00</tns:StartDate>
       <tns:TerminationDate xsi:type="xsd:date">2008-04-18-04:00
           </tns:TerminationDate>
    </tns:row>

    カラム名とデータ型が含まれていることに注意してください。

    プロキシの使用

    XML メッセージ・トラフィックを記録するプロキシ・ソフトウェアを使用して、上記の応答を確認することができます。プロキシは、クライアント・アプリケーションと Web サーバの間に挿入されます。

    EmployeeList 結果セットは、SASoapDemo アプリケーションによって「(型)カラム=値」のペアで表示されます。生成される出力は次のようになります。

    EmployeeList 結果セットが「カラム名=値」のペアで表示されます。生成される出力は次のようになります。

    Number of columns=4
    EmployeeID=102
    Surname=Whitney
    GivenName=Fran
    StartDate=1984-08-28-04:00
    
    Number of columns=4
    EmployeeID=105
    Surname=Cobb
    GivenName=Matthew
    StartDate=1985-01-01-05:00
    .
    .
    .
    Number of columns=4
    EmployeeID=1740
    Surname=Nielsen
    GivenName=Robert
    StartDate=1994-06-24-04:00
    
    Number of columns=5
    EmployeeID=1751
    Surname=Ahmed
    GivenName=Alex
    StartDate=1994-07-12-04:00
    TerminationDate=2008-04-18-04:00

    TerminationDate カラムが送信されるのは、その値が NULL でない場合だけです。この例では、終了日に NULL 以外の値が設定され、Employees テーブルの最後のローが変更されました。

    また、日付値には UTC (協定世界時) からのオフセットが含まれています。前述のサンプル・データでは、サーバは北米東部のタイムゾーンに属する場所にあります。つまり、標準時間の場合は UTC よりも 5 時間早く (-05:00)、夏時間の場合は UTC よりも 4 時間早い (-04:00) ことになります。