40.3. スタブコードの生成

概要

非同期スタイルの呼び出しには、SEI で定義された専用の非同期メソッド用の追加のスタブコードが必要です。この特別なスタブコードは、デフォルトでは生成されません。非同期機能をオンにして必要なスタブコードを生成するには、WSDL 2.0 仕様のマッピングカスタマイズ機能を使用する必要があります。

カスタマイズにより、Maven コード生成プラグインがスタブコードを生成する方法を変更できます。特に、WSDL から Java へのマッピングを変更したり、特定の機能をオンにしたりすることができます。ここでは、カスタマイズを使用して非同期呼び出し機能をオンにします。カスタマイズは、jaxws:bindings タグを使用して定義するバインディング宣言を使用して指定されます (ここでは、jaxws 接頭辞は http://java.sun.com/xml/ns/jaxws namespace に関連付けられます)。バインディング宣言を指定する方法は 2 つあります。

外部バインディング宣言
外部バインディング宣言を使用する場合、jaxws:bindings 要素は WSDL コントラクトとは別のファイルで定義されます。スタブコードを生成するときに、コードジェネレーターへのバインディング宣言ファイルの場所を指定します。
埋め込みバインディング宣言
組み込みバインディング宣言を使用する場合は、jaxws:bindings 要素を直接 WSDL コントラクトに組み込み、それを WSDL 拡張として扱います。この場合、jaxws:bindings の設定は直接の親要素にのみ適用されます。

外部バインディング宣言の使用

非同期呼び出しをオンにするバインディング宣言ファイルのテンプレートを 例40.2「非同期バインディング宣言のテンプレート」 に示します。

例40.2 非同期バインディング宣言のテンプレート

<bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
          wsdlLocation="AffectedWSDL"
          xmlns="http://java.sun.com/xml/ns/jaxws">
  <bindings node="AffectedNode">
    <enableAsyncMapping>true</enableAsyncMapping>
  </bindings>
</bindings>

ここで、AffectedWSDL は、このバインディング宣言の影響を受ける WSDL コントラクトの URL を指定します。AffectedNode は、WSDL コントラクトのどのノードがこのバインディング宣言の影響を受けるかを指定する XPath 値です。WSDL コントラクト全体が影響を受けるようにするには、AffectedNodewsdl:definitions に設定できます。非同期呼び出し機能を有効にするには、jaxws:enableAsyncMapping 要素を true に設定します。

たとえば、GreeterAsync インターフェイスに対してのみ非同期メソッドを生成する場合は、前のバインディング宣言で <bindings node="wsdl:definitions/wsdl:portType[@name='GreeterAsync']"> を指定できます。

バインディング宣言がファイル async_binding.xml に保存されている場合、例40.3「コンシューマーコード生成」に記載されているように POM を設定します。

例40.3 コンシューマーコード生成

<plugin>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-codegen-plugin</artifactId>
  <version>${cxf.version}</version>
  <executions>
    <execution>
      <id>generate-sources</id>
      <phase>generate-sources</phase>
      <configuration>
        <sourceRoot>outputDir</sourceRoot>
        <wsdlOptions>
          <wsdlOption>
            <wsdl>hello_world.wsdl</wsdl>
            <extraargs>
              <extraarg>-client</extraarg>
              <extraarg>-b async_binding.xml</extraarg>
            </extraargs>
          </wsdlOption>
        </wsdlOptions>
      </configuration>
      <goals>
        <goal>wsdl2java</goal>
      </goals>
    </execution>
  </executions>
</plugin>

-b オプションは、コードジェネレーターに対し、外部バインディングファイルの場所を指定します。

コードジェネレーターの詳細は、「cxf-codegen-plugin」 を参照してください。

埋め込みバインディング宣言の使用

また、jaxws:bindings 要素とその関連の jaxws:enableAsynchMapping 子要素を直接 WSDL に配置して、バインディングのカスタマイズをサービスを定義する WSDL ドキュメントに直接組み込むこともできます。また、jaxws 接頭辞の namespace 宣言を追加する必要もあります。

例40.4「非同期マッピングのための組み込みバインディング宣言を備えた WSDL」 は、操作の非同期マッピングをアクティブ化するバインディング宣言が埋め込まれた WSDL ファイルを示しています。

例40.4 非同期マッピングのための組み込みバインディング宣言を備えた WSDL

<wsdl:definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
                  ...
                  xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
                  ...>
  ...
  <wsdl:portType name="GreeterAsync">
    <wsdl:operation name="greetMeSometime">
      <jaxws:bindings> <jaxws:enableAsyncMapping>true</jaxws:enableAsyncMapping> </jaxws:bindings>
      <wsdl:input name="greetMeSometimeRequest"
                  message="tns:greetMeSometimeRequest"/>
      <wsdl:output name="greetMeSometimeResponse"
                   message="tns:greetMeSometimeResponse"/>
    </wsdl:operation>
  </wsdl:portType>
  ...
</wsdl:definitions>

バインディング宣言を WSDL ドキュメントに埋め込む場合、宣言を配置する場所を変更することで、宣言の影響を受けるスコープを制御できます。宣言が wsdl:definitions 要素の子として配置されると、コードジェネレーターは、WSDL ドキュメントに定義されたすべての操作に非同期メソッドを作成します。wsdl:portType 要素の子として配置されると、コードジェネレーターは、インターフェイスに定義されたすべての操作に非同期メソッドを作成します。wsdl:operation 要素の子として配置されると、コードジェネレーターは、その操作にのみ非同期メソッドを作成します。

埋め込み宣言を使用する場合、コードジェネレーターに特別なオプションを渡す必要はありません。コードジェネレーターはそれらを認識し、それに応じて動作します。

生成されたインターフェイス

この方法でスタブコードを生成した後、GreeterAsync SEI (ファイル GreeterAsync.java 内) は 例40.5「非同期呼び出しのメソッドを使用したサービスエンドポイントインターフェイス」に示すように定義されます。

例40.5 非同期呼び出しのメソッドを使用したサービスエンドポイントインターフェイス

package org.apache.hello_world_async_soap_http;

import org.apache.hello_world_async_soap_http.types.GreetMeSometimeResponse;
...

public interface GreeterAsync
{
  public Future<?> greetMeSometimeAsync(
        java.lang.String requestType,
        AsyncHandler<GreetMeSometimeResponse> asyncHandler
    );

    public Response<GreetMeSometimeResponse> greetMeSometimeAsync(
        java.lang.String requestType
    );

    public java.lang.String greetMeSometime(
        java.lang.String requestType
    );
}

通常の同期メソッド greetMeSometime() のほかに、greetMeSometime 操作用に 2 つの非同期メソッドも生成されます。

  • コールバックのアプローチ: publicFuture<?>greetMeSomtimeAsyncjava.lang.StringrequestTypeAsyncHandler<GreetMeSomtimeResponse>asyncHandler
  • ポーリングのアプローチ: publicResponse<GreetMeSomeTimeResponse>greetMeSometimeAsyncjava.lang.StringrequestType