2.6. Webサービスクライアントの作成

ここでは、作成した Web サービスを呼び出す Web サービスクライアントを作成する方法について説明します。

2.6.1. JAX-WS準拠のクライアント生成(ウィザード)

Webサービス参照ウィザードを使うと、JAX-WS 準拠の Web サービスクライアントを作成することができます。

2.6.1.1. Webサービス参照ウィザードの初期設定

Webサービスの作成 の 「Webサービス作成ウィザードを使用する前に」をご覧ください。

2.6.1.2. Web サービス参照ウィザードの起動

Web サービス参照ウィザードの起動方法は二つあります。

新規ダイアログ

WebOTX Developer (with Developer's Studio) のメニューから ファイル > 新規 > その他 を選択すると、 新規ダイアログが起動します。

Web サービス参照ウィザードを開始するには、 Web サービス > Web サービス参照 を選択し、次へをクリックします。

新規 Web サービス Web サービス参照

ポップアップメニュー

プロジェクトを選択し、WebOTX Developer (with Developer's Studio) の右クリックメニューから Web サービス > Web サービス参照 を選択すると、 Web サービス参照 ダイアログが起動します。

ナビゲーター Web サービス Web サービス参照

2.6.1.3. Web サービス参照ウィザード

Web サービス参照ウィザードを使用して、JAX-WS 準拠の Web サービスクライアントを作成する方法を説明した図です。 アプリケーションは、自動生成されるクライアントコードを用いて Web サービスと通信します。 クライアントコードを利用する呼び出しコードも自動生成することができます。 外部環境プロパティを利用して、WSDL の参照先を切り替えることにより、利用する Web サービスを 例えば本番環境とテスト環境で、切り替えることもできます。

作成するアプリケーション

Web サービス参照ウィザードを使用して、Web サービス参照をプロジェクトに追加すると、 以下のことができるようになります。

以下では、SOAP Webサービスの作成 で作成した Web サービスを呼び出す例を用いて、説明を行います。

Web サービス参照

Web サービス参照ウィザードを下記の説明を参考に設定します。

項目 説明
ソース・フォルダー クライアントコードを生成するプロジェクトとソース・フォルダーを指定します
WSDL の URL を指定して作成 利用する Web サービスの WSDL の URL を指定します。file:// プロトコルも指定できます。
ワークスペース内の WSDL から作成 利用する Web サービスの WSDL がワークスペース内にある場合にはこちらで指定します。
生成するクライアントのパッケージを指定 「WSDLから作成」にチェックをした場合は、Web サービスのネームスペースからパッケージ名を作成します。 「生成するクライアントのパッケージを指定」にチェックした場合には、任意のパッケージ名を指定できます。
非同期呼び出しを行う クライアントコードを非同期呼び出し対応にする場合にはチェックします。 詳細は、呼び出しコードの生成 で説明します。
WSDL のロケーションを外部環境プロパティに設定する WSDL のロケーションを外部環境プロパティに設定し、切り替え可能にする場合にはチェックします。 指定したソース・フォルダーに外部環境プロパティが設定されており、なおかつ、 ウィザードの他の項目が正しく設定されている場合にチェック可能になります。 外部環境プロパティは、[開発環境の構築(WebOTX Developer) > 外部環境プロパティ]を参照してください。 詳細は、外部環境プロパティの利用 で説明します。

設定が完了したら、完了 ボタンをクリックします。

処理が完了すると、プロジェクトは以下の構成になります。

プロジェクト・エクスプローラー プロジェクト 構成

sample.hello パッケージが生成されたクライアントコードです (1)。 Web サービス参照ノード は、設定した Web サービスがサービス名、WSDL、サービス、ポート、オペレーション、 呼び出し方式の順にツリーが生成されます (2)。 references ディレクトリは、読み込んだ WSDL や XSD がコピーされます (3)。

Memo

すでに Web サービス参照が登録されている場合で、新規作成しようとしている Web サービス参照が 以下の条件を満たす場合は、同一 Web サービスとしてみなし、新規作成ではなく更新処理になります。

Memo
Web サービス参照 は SOAP 1.1 のみに対応しています。 SOAP 1.2 には対応していませんので、ご注意ください。

Caution
WSDLのURLにlocalhostを指定した場合、特定の環境では、プロキシー除外設定がうまくいかず、 wsimportコマンドの実行に失敗した旨のエラーが表示されることがあります。 この場合は、localhostではなく、作業マシンのIPアドレスを指定してください。

呼び出しコードの生成

Web サービスの呼び出しコードを生成する方法について説明します。 Web サービスの呼び出しコードを生成するには、プロジェクト・エクスプローラーの Web サービス参照 ノードを利用します。

Memo
Web サービス参照 ノードは プロジェクト・エクスプローラー でのみ表示されます。 J2EE パースペクティブに切り替えて、プロジェクト・エクスプローラーを表示してお使いください。

呼び出したいオペレーションの下の 同期呼び出しノード、 非同期呼び出し(コールバック)ノード、 非同期呼び出し(ポーリング)ノードのいずれかを、 エディタの呼び出しコードを挿入したい場所にドラッグ&ドロップします。

プロジェクトエクスプローラー 呼び出し方式 呼び出しコード生成

ドラッグ&ドロップが完了すると、そのオペレーションを指定した方式で呼び出すのに必要なコードが生成されます。

同期呼び出しの場合:

package main;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
try { // web service reference for HelloService();
	sample.hello.HelloService port = service.getHelloServicePort();
	// TODO initialize arguments
	java.lang.String arg0 = "";
	java.lang.String result = port.sayHello(arg0);
	// TODO process result
	System.out.println(result);
} catch (Exception e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
} // web service reference for HelloService

	}

}

非同期呼び出し(ポーリング)の場合:

package main;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
try { // web service reference for HelloService
	final int WAIT_TIME = 500;
	sample.hello.HelloService_Service service = new sample.hello.HelloService_Service();
	sample.hello.HelloService port = service.getHelloServicePort();
	// TODO initialize arguments
	java.lang.String arg0 = "";
	jakarta.xml.ws.Response<sample.hello.SayHelloResponse> res = port
			.sayHelloAsync(arg0);
	while (!res.isDone()) {
		Thread.sleep(WAIT_TIME);
	}
	// TODO process response
	System.out.println(res.get().getReturn());
} catch (Exception e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
} // web service reference for HelloService


	}


}

Caution
生成したコード[res.get()]の後に、に手動で[.getXXX()]を追加する必要があります。この例では、[.getReturn()]です。
追加前:
    System.out.println(res.get());
追加後:
    System.out.println(res.get().getReturn());

非同期呼び出し(コールバック)の場合:

package main;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
try { // web service reference for HelloService
	final int WAIT_TIME = 500;
	sample.hello.HelloService_Service service = new sample.hello.HelloService_Service();
	sample.hello.HelloService port = service.getHelloServicePort();
	// TODO initialize arguments
	java.lang.String arg0 = "";
	jakarta.xml.ws.AsyncHandler<sample.hello.SayHelloResponse> handler = new jakarta.xml.ws.AsyncHandler<sample.hello.SayHelloResponse>() {
		public void handleResponse(
				jakarta.xml.ws.Response<sample.hello.SayHelloResponse> res) {
			try {
				// TODO process result
				System.out.println(res.get().getReturn());
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	};
	java.util.concurrent.Future<?> result = port.sayHelloAsync(arg0,
			handler);

	while (!result.isDone()) {
		Thread.sleep(WAIT_TIME);
	}
} catch (Exception e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
} // web service reference for HelloService
	}

}

Caution
生成したコード[res.get()]の後に、に手動で[.getXXX()]を追加する必要があります。この例では、[.getReturn()]です。
追加前:
    System.out.println(res.get());
追加後:
    System.out.println(res.get().getReturn());

生成された呼び出しコードのインデントを整えたい場合には、整形したい部分を選択して、 Ctrl + Shift + F を押してください。

生成された呼び出しコードは、引数の部分が設定されていないため、引数を設定します。 下記の例では、同期呼び出しの呼び出しコード上の arg0Bob を設定しています。

package main;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try { // web service reference for HelloService();
			sample.hello.HelloService port = service.getHelloServicePort();
			// TODO initialize arguments
			java.lang.String arg0 = "Bob";
			java.lang.String result = port.sayHello(arg0);
			// TODO process result
			System.out.println(result);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} // web service reference for HelloService

	}

}

ここまで設定を行った後で、main.Main クラスを実行すると Web サービスの呼び出しが行われます。

クラス実行 コンソール 出力結果

2.6.1.4. 非同期呼び出し

Web サービス参照ウィザードでは、以下の3つの呼び出し方式をサポートしています。

ここでは、それぞれの呼び出し方式について説明します。

同期呼び出し

Web サービスの呼び出しを同期的に行います。Web サービスの呼び出しが完了するまで待つため、 他の処理ができませんが、記述がシンプルになります。

非同期呼び出し(コールバック)

Web サービスの呼び出しを非同期的に行います。Web サービスの呼び出しの完了を待たずに 処理を続けることができます。Web サービスの呼び出しの完了は、作成したスレッドの上のイベントハンドラが受け取ります。 記述は複雑になりますが、非同期呼び出し(ポーリング)のようにサーバに Web サービスの呼び出しの完了確認を定期的に 行う処理の記述をする必要がありません。

非同期呼び出し(ポーリング)

Web サービスの呼び出しを非同期的に行います。Web サービスの呼び出しの完了を待たずに 処理を続けることができます。Web サービスの呼び出しの完了を確認するために、定期的にサーバに問い合わせを行います。 問い合わせ間隔が長くなれば、それだけWeb サービスの呼び出しの完了のタイミングが遅くなりますが、 任意のタイミングで Web サービスの呼び出し結果を取得することができます。

2.6.1.5. 外部環境プロパティの利用

外部環境プロパティを利用して、WSDL のロケーションを変更する方法について説明します。 この機能は、例えば、参照する WSDL の内容が同じで、デプロイ先がテスト環境から本番環境に切り替わった場合に、 Web サービス参照を作り直すことなく、設定を切り替えるだけで対応を可能にすることができます。

Web サービス参照ウィザードで WSDL のロケーションを外部環境プロパティに設定する が有効だった場合、 WSDL のロケーションは外部環境プロパティに設定されます。 下記の例では、ExternalEnvironment.javaotx-env.properties が外部環境プロパティに関するファイルです。 外部環境プロパティが設定されたソース・フォルダーに Web サービス参照を設定した場合、 外部環境プロパティに関するファイルは 上書きされ、Web サービス参照に対応したファイルに変更されます。

プロジェクト・エクスプローラー 外部環境プロパティに関するファイル

Web サービスの呼び出しコードを生成すると、以下のようなコードが挿入されます。

同期呼び出しの場合:

package main;

public class Main {

  /**
   * @param args
   */
  public static void main(String[] args) {

    try { // web service reference for HelloService
      sample.hello.HelloService_Service service = new sample.hello.HelloService_Service(
        webotx.ds.ExternalEnvironment.getURL("HelloService"),
        webotx.ds.ExternalEnvironment.getService("HelloService"));
      sample.hello.HelloService port = service.getHelloServicePort();
      // TODO initialize arguments
      java.lang.String arg0 = "";
      java.lang.String result = port.sayHello(arg0);
      // TODO process result
      System.out.println(result);
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } // web service reference for HelloService
  }
}

WSDL のロケーションを変更する場合には、プロジェクトの右クリックメニューから 構成 > 外部環境プロパティの設定 をクリックし、 該当するプロパティの値を変更します。

外部環境プロパティの設定

この例では、開発中に切り替えていますが、パッケージを作って後の運用時に外部環境プロパティを変更することもできます。 詳細については、 [ 開発環境の構築(WebOTX Developer) > 外部環境プロパティ ] を参照してください。

2.6.1.6. Web サービス参照の追加

Web サービス参照の追加機能について説明します。プロジェクト・エクスプローラーの Web サービス参照 ノードの右クリックメニューから Web サービス参照の追加 をクリックすると、Web サービス参照ウィザードが表示されます。 機能は、メニューや、プロジェクトの右クリックメニューから呼び出した場合と違いはありません。

Web サービス参照の追加

2.6.1.7. Web サービス参照の全削除

Web サービス参照の全削除機能について説明します。プロジェクト・エクスプローラーの Web サービス参照 ノードの右クリックメニューから Web サービス参照の全削除 をクリックすると、確認ダイアログが表示されます。

Web サービス参照の全削除

Web サービス参照の全削除 削除の確認

はい をクリックした場合には、Web サービス参照に関するファイルである以下のファイルが削除されます。

いいえ をクリックした場合には、キャンセルされます。

2.6.1.8. Web サービス参照の更新

Web サービス参照の更新機能について説明します。プロジェクト・エクスプローラーの サービス名 ノードの右クリックメニューから Web サービス参照の更新 をクリックすると、確認ダイアログが表示されます。

Web サービス参照の更新

Web サービス参照の更新 更新の確認

はい をクリックした場合には、Web サービス参照に関するファイルである以下のファイルが更新されます。

ドラッグ&ドロップで生成されたサービスの呼び出しコードは更新されませんので、手動で更新してください。

いいえ をクリックした場合には、キャンセルされます。

2.6.1.9. Web サービス参照の削除

Web サービス参照の削除機能について説明します。プロジェクト・エクスプローラーの サービス名 ノードの右クリックメニューから Web サービス参照の削除 をクリックすると、確認ダイアログが表示されます。

Web サービス参照の削除

Web サービス参照の削除

はい をクリックした場合には、Web サービス参照に関するファイルである以下のファイルが削除されます。

ドラッグ&ドロップで生成されたサービスの呼び出しコードは削除されませんので、手動で削除してください。

いいえ をクリックした場合には、キャンセルされます。

2.6.2. JAX-WS準拠のクライアント作成(コマンド)

クライアントアプリケーションは、プロキシ(サービスエンドポイントインタフェースを実装したスタブ)、もしくはDispatchを利用してリモートのWebサービスエンドポイントにアクセスすることができます。ここでは、プロキシを使用したアプリケーションを説明します。
環境設定
環境変数JAVA_HOMEに、JDKインストールディレクトリを指定してください。また、javacコマンドがコマンド検索パスに加わるよう、環境変数PATHに<JAVA_HOME>/binを追加してください。
wsimport を実行するため、環境変数PATHに<WebOTX_DIR>/binを追加してください。
また、JAX-WSアプリケーションを作成する場合は次のライブラリをクラスパスに含めてください。環境変数CLASSPATHに設定すると仮定して説明します。

Caution
Webサービスアプリケーションを作成する場合は環境変数に以下も追加が必要です。
・JAVA_TOOL_OPTIONS=-Dcom.nec.webotx.webservice.tools.ws.Invoker.noSystemProxies=true

Memo
<WebOTX_DIR>はWebOTXのインストールディレクトリに読み替えてください。

2.6.2.1. プロキシを使用したクライアント
サーバアプリケーションの開発で作成したサンプルのクライアントアプリケーションを作成するためのファイル構成は、以下の通りです。サーバアプリケーションを開発したディレクトリ以外の任意のディレクトリに、次のファイルを作成してください。ファイルの内容については、以下で説明します。
ディレクトリ ファイル
src/main/java/sample HelloClient.java
クライアントアプリケーションを開発する手順は次のようになります。
1. プロキシの生成
wsimportコマンドを使用してサービスエンドポイントインタフェースのプロキシやサービスエンドポイントインタフェースのリファレンスを取得するためのサービスクラス、Request/Response Beanなどを生成します。
あらかじめ、[ JAX-WS(コマンド) ]のサーバアプリケーションの作成で説明したhellowsサンプルをWebOTXに配備したのち、src/main/javaディレクトリにて以下のコマンドを実行してください。なお、以下のコマンドを実行する前に、あらかじめ出力ディレクトリclassesを作成しておいてください。
src> wsimport -d ../classes -s main/java -keep http://localhost/hellows/hello?wsdl
wsimportコマンドの詳細に関しては、 [ コマンドリファレンス > wsimport ] を参照してください。
これにより、次のファイルが生成されます。(Webサービスエンドポイント実装クラスからサーバアプリケーションを作成した場合)
ディレクトリ ファイル
src/main/java/sample/ Hello.java Hello_Service.java SayHello.java SayHelloResponse.java ObjectFactory.java package-info.java
classes/sample/ Hello.class Hello_Service.class SayHello.class SayHelloResponse.class ObjectFactory.class package-info.class
2. クライアントアプリケーションの作成
プロキシを使用したクライアントアプリケーションは次のようになります。
HelloClient.java
package sample;

public class HelloClient {
  public static void main(String[] args) {
    Hello_Service service = new Hello_Service();
    Hello port = service.getHelloPort();
    HelloClient client = new HelloClient();
    client.hello(port);
  }

  private void hello(Hello port){
    try {
      System.out.println(port.sayHello("WebOTX"));
    } catch( java.lang.Exception e) {
      e.printStackTrace();
    }
  }
}
上記コードのように、サービスクラスのgetHelloPort()メソッドで、プロキシ(スタブ)を取得することができます。
以上の作業が終了したら、クライアントクラスをコンパイルします。
src> javac -d ../classes -cp %CLASSPATH%;../classes main/java/sample/HelloClient.java
最後に、クライアントクラスを実行します。srcディレクトリの上のディレクトリで実行してください。
> java -cp %CLASSPATH%;classes sample.HelloClient
正常に実行が完了すれば、次のような結果が出力されます。
Hello WebOTX!
2.6.2.2. Dispatchを使用したクライアント
Dispatchは動的なWebサービス呼び出しのインタフェースとして利用できます。Dispatchを使用したクライアントアプリケーションを、以下の3つの方法に分けて説明します。
・javax.xml.transform.Sourceを使用する方法
・jakarta.xml.bind.JAXBContextを使用する方法
・jakarta.xml.soap.SOAPMessageを使用する方法
以下の例でDispatchオブジェクトを生成している、createDispatchメソッドの第3パラメタで指定するService.Modeには以下を指定します。
Service.Modeの値 説明
MESSAGE SOAPメッセージ全体を扱います。SourceおよびSOAPMessageを利用する場合に指定できます。
PAYLOAD SOAPメッセージの本体のみを扱います。SourceおよびJAXBを利用する場合に指定できます。
・javax.xml.transform.Sourceを使用する方法
メッセージをStreamやDOM/SAXで扱う方法です。
HelloClientSource.java
package sample;

import java.io.StringReader;
import jakarta.xml.ws.Dispatch;
import jakarta.xml.ws.Service;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.Source;

public class HelloClientSource {
public static void main(String[] args) { Service service = new Hello_Service(); QName portQName = new QName("http://sample","HelloPort"); String request = "<ns1:sayHello xmlns:ns1=\"http://sample\">" +"<arg0>WebOTX</arg0></ns1:sayHello>"; try { Dispatch<Source> sourceDispatch = service.createDispatch( portQName,Source.class, Service.Mode.PAYLOAD); Source result = sourceDispatch.invoke( new StreamSource(new StringReader(request))); } catch (Exception e) { e.printStackTrace(); } } }
・jakarta.xml.bind.JAXBContextを使用する方法
JAXBを利用して、メッセージをシリアライズ/デシリアライズする方法です。
HelloClientJAXBContext.java
package sample;

import jakarta.xml.ws.Dispatch;
import jakarta.xml.ws.Service;
import javax.xml.namespace.QName;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;

public class HelloClientJAXBContext {
  public static void main(String[] args) {
    Service service = new Hello_Service();
    QName portQName = new QName("http://sample","HelloPort");
    try {
      JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
      Dispatch jaxbDispatch = service.createDispatch(portQName,jaxbContext, Service.Mode.PAYLOAD);
      ObjectFactory factory = new ObjectFactory();
      SayHello msg = new SayHello();
      msg.setArg0("WebOTX");
      JAXBElement<SayHello> sayHello = factory.createSayHello(msg);
      JAXBElement<SayHelloResponse> response = (JAXBElement<SayHelloResponse>) jaxbDispatch.invoke(sayHello);
      SayHelloResponse result = response.getValue();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
・jakarta.xml.soap.SOAPMessageを使用する方法
メッセージをSAAJのSOAPMessageで扱う方法です。
HelloClientSOAPMessage.java
package sample;

import jakarta.xml.soap.*;
import java.io.StringReader;
import jakarta.xml.ws.Dispatch;
import jakarta.xml.ws.Service;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.Source;

public class HelloClientSOAPMessage {
  public static void main(String[] args) {
    Service service = new Hello_Service();
    QName portQName = new QName("http://sample","HelloPort");
    String request = "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">" + "<S:Body><ns1:sayHello xmlns:ns1=\"http://sample\"><arg0>WebOTX</arg0>" + "</ns1:sayHello></S:Body></S:Envelope>";
    try {
      SOAPMessage message = null;
      MessageFactory factory = MessageFactory.newInstance();
      message = factory.createMessage();
      message.getSOAPPart().setContent( (Source) new StreamSource(new StringReader(request)));
      message.saveChanges();
      Dispatch<SOAPMessage> dispatch = service.createDispatch( portQName,SOAPMessage.class, Service.Mode.MESSAGE);
      SOAPMessage response = dispatch.invoke(message);
      Source result = response.getSOAPPart().getContent();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

2.6.2.3. Fast Infoset の利用方法
Fast Infosetを利用するには、次のうちいずれかの方法で設定します。
(1)クライアントクラスにソースコードを追加する

[ソースコード例]
Service service = new Service(?);
ServiceEndpointInterface proxy = service.get?();
java.util.Map<String, Object> ctxt = ((jakarta.xml.ws.BindingProvider)proxy).getRequestContext();
ctxt.put(com.nec.webotx.webservice.xml.ws.developer.
JAXWSProperties.CONTENT_NEGOTIATION_PROPERTY, "***value***");
[ソースコードの説明]
「Service」というクラスはjakarta.xml.ws.Serviceをextendsしたクラスです。実際にはwsimportコマンドやWebサービス作成ウィザードで生成されたクラスを使用します。「ServiceEndpointInterface」というクラスはサービスエンドポイントインタフェースです。実際にはwsimportコマンドやWebサービス作成ウィザードで生成されたインタフェースクラスを使用します。***value***には、下の表に示す三つのうちのいずれかの値を指定します。 (2)クライアント実行時にJava VMプロパティを追加する

[設定例]
java -Dcom.nec.webotx.webservice.xml.ws.client.ContentNegotiation=***value*** クライアントクラス
なお、「***value***」には次のうちいずれかの値を指定します。
意味
none Fast Infoset を使用しない
pessimistic レスポンスメッセージのみFast Infoset を利用する
optimistic リクエストメッセージ・レスポンスメッセージの両方でFast Infoset を利用する

2.6.3. SAAJ APIを使用したクライアント作成

SAAJのAPIを利用し、Webサービスと交換するSOAPメッセージを直接処理するタイプのクライアントを作成できます。
環境構築
SAAJのAPIを利用したクライアントをコンパイル、実行する環境には、次のライブラリがクラスパスに追加されている必要があります。

Caution
Webサービスアプリケーションを作成する場合は環境変数に以下も追加が必要です。
・JAVA_TOOL_OPTIONS=-Dcom.nec.webotx.webservice.tools.ws.Invoker.noSystemProxies=true

Memo
<WebOTX_DIR>はWebOTXのインストールルートディレクトリのことです。

クライアントコードの作成
「SAAJ」サンプルをベースに、クライアントコードの作成方法について説明します。
import java.io.OutputStream;
import java.util.Iterator;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import jakarta.xml.soap.MessageFactory;
import jakarta.xml.soap.Name;
import jakarta.xml.soap.SOAPBody;
import jakarta.xml.soap.SOAPBodyElement;
import jakarta.xml.soap.SOAPConnection;
import jakarta.xml.soap.SOAPConnectionFactory;
import jakarta.xml.soap.SOAPEnvelope;
import jakarta.xml.soap.SOAPException;
import jakarta.xml.soap.SOAPMessage;

public class SAAJClient {
    //サービスのURLです。
    private static final String URL = "http://localhost/saaj_service/sample";
    //SOAPメッセージの作成に使用する値です。
    private static final String NS = "http://sample/WebOTX"; //名前空間
    private static final String PREFIX = "n"; //プレフィックス
    private static final String ELEMENT1 = "data"; //要素名
    private static final String ELEMENT2 = "No"; //要素名

    /**
     * メインメソッド
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        SAAJClient client = new SAAJClient();
        
        //Webサービスを実行し、結果をコンソールに表示します。
        //リクエストメッセージはプログラミングにより、1要素ずつ作成します。
        client.invoke(client.createMessage(), System.out);
        
        //結果表示にあたり、空白行を挿入します。
        System.out.println();
        System.out.println();
        
        //Webサービスを実行し、結果をコンソールに表示します。リクエストメッセージ
        //は、あらかじめSOAPBodyが記述されているXMLファイルを読み込み、作成します。
        client.invoke(client.createMessage("sample.xml"), System.out);
    }

    /**
     * Webサービスを実行します。引数で渡されたSOAPMessageがリクエストメッセージに
     * なります。
     *
     * @param message
     * @param out
     */
    private void invoke(SOAPMessage message, OutputStream out) {
        try {
            //コネクションを張ります。
            SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
            SOAPConnection con = scf.createConnection();
            
            //Webサービスを実行して、サービスから返されたレスポンスメッセージ
            //を受け取ります。
            SOAPMessage reply = con.call(message, URL);

            //SOAPBodyを取り出します。
            SOAPBody body = reply.getSOAPBody();
            
            //SOAPBodyのエレメントを取り出します。
            Iterator ite = body.getChildElements();
            
            //SOAPBodyから取り出したノードをXML形式に整形して
            //出力します。
            while (ite.hasNext()) {
                Node node = (Node) ite.next();
                Source source = new DOMSource(node);
                TransformerFactory factory = TransformerFactory.newInstance();
                Transformer transformer = factory.newTransformer();
                Result output = new StreamResult(out);
                transformer.transform(source, output);
            }
            //コネクションを閉じます。
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * SOAPMessageをSAAJプログラミングにより作成します。
     *
     * @return
     * @throws SOAPException
     */
    private SOAPMessage createMessage() throws SOAPException {
        //SOAPMessageを作成します。
        MessageFactory mf = MessageFactory.newInstance();
        SOAPMessage message = mf.createMessage();
        
        //SOAPMessageからSOAPPartを取り出し、さらにSOAPEnvelopeを
        //取り出します。
        SOAPEnvelope env = message.getSOAPPart().getEnvelope();
        
        //SOAPEnvelopeからSOAPBodyを取り出します。
        SOAPBody body = env.getBody();
        
        //SOAPBodyに各要素を追加します。
        Name name = env.createName(ELEMENT1, PREFIX, NS);
        SOAPBodyElement bodyElement = body.addBodyElement(name);
        name = env.createName(ELEMENT2, PREFIX, NS);
        bodyElement.addChildElement(name).addTextNode("001");
        
        //作成したSOAPMessageを返します。
        return message;
    }

    /**
     * XMLを読み込み、SOAPメッセージを作成します。
     *
     * @param filelocation
     * @return
     * @throws Exception
     */
    private SOAPMessage createMessage(String filelocation) throws Exception {
        //SOAPMessageを作成します。
        MessageFactory mf = MessageFactory.newInstance();
        SOAPMessage message = mf.createMessage();
        
        //SOAPMessageからSOAPPartを取り出し、さらにSOAPEnvelopeを
        //取り出します。
        SOAPEnvelope env = message.getSOAPPart().getEnvelope();
        
        //SOAPEnvelopeからSOAPBodyを取り出します。
        SOAPBody body = env.getBody();
        
        //DOMを使用して、SOAPBodyが記述されているXMLファイルを読み
        //込み、SOAPBodyに追加します。
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(filelocation);
        
        //SOAPBodyに追加します。
        body.addDocument(doc);
        
        //作成したSOAPMessageを返します。
        return message;
    }
}

クライアントの実行
メニューから、実行 > 実行構成を選択し、実行構成ダイアログを開きます。[Java アプリケーション]を右クリックして「新規構成」を選択します。名前を適宜変更します。「メイン」タブで、「プロジェクト」に作成しておいたJavaプロジェクトを、「メインクラス」に作成したクライアントのクラスを指定します。引数を指定したい場合は、「引数」タブで指定します。以上の設定を確認したら[実行]ボタンを押します。
 

2.6.4. JAX-RS 準拠のクライアント作成

クライアントとして、Webブラウザを利用する場合、特にクライアントを作成する必要はありません。
クライアントを作成する場合については、具体例を、 [チュートリアル > Webサービスクライアントの作成 > JAX-RS の場合 ] に記載していますのでご覧ください。