Cosminexus アプリケーションサーバ V8 Webサービス開発の手引
スタブベースのWebサービスクライアントの実装例について説明します。
スタブベースのWebサービスクライアントを実行する場合,WSDLのパスまたはURLが必要になります。このとき,次の条件の組み合わせによって,参照されるWSDLが異なります。
各条件の組み合わせと,参照されるWSDLの対応を次の表に示します。それぞれの条件の場合の例については,「3.6.1(5)(a) サービスクラスをインスタンス化する」を参照してください。
表3-5 条件の組み合わせと参照されるWSDLの対応
| 項番 | 利用するコンストラクタ | -wsdllocation オプション |
参照されるWSDL |
|---|---|---|---|
| 1 | デフォルトコンストラクタ | × | cjwsimportコマンドの引数に指定したWSDL※1 |
| 2 | デフォルトコンストラクタ | ○ | -wsdllocationオプションに指定したWSDL※2 |
| 3 | java.net.URL オブジェクトおよびjavax.xml.namespace.QNameオブジェクトをパラメタに持つコンストラクタ | − | パラメタのURLに指定したWSDL※2 |
接続するWebサービスのURL(エンドポイントアドレス)は,デフォルトではWSDLのポート(wsdl:port要素)が持つアドレス情報(soap:address子要素のlocation属性)が利用されます。ただし,メッセージコンテキストのjavax.xml.ws.service.endpoint.addressプロパティを利用すると,エンドポイントアドレスを動的に変更できます。エンドポイントアドレスを動的に変更する例については,「3.6.1(5)(c) ポートのメソッドを呼び出す」を参照してください。
サービスクラスの生成には処理コストが掛かるので,一度生成したサービスクラスは再利用することをお勧めします。ポートを取得するためにサービスクラスを複数回生成する必要はありません。同様に,ポートの取得にも処理コストが掛かるので,一度取得したポートは再利用することをお勧めします。ポートのWebメソッドを複数回呼び出すためにポートを複数回取得する必要はありません。ただし,複数スレッドでポートを共有する場合,共有するポートの要求コンテキストのプロパティに対する変更は,複数スレッドが動作する前に実行してください。複数スレッドの動作中に変更すると,通信が失敗したり,不正なSOAPメッセージが送信されたりすることがあります。
WebサービスクライアントをサーブレットやEJBなどで実装する場合は,それぞれの初期化メソッドでサービスクラスの生成,またはポートの取得を実施し,再利用してください。ポートの要求コンテキストのプロパティに対する変更も,それぞれの初期化メソッドで実行してください。
呼び出すWebサービスのWSDLに複数のサービス(wsdl:service要素)が含まれる場合,サービスクラスを生成するときに,java.net.URLオブジェクトとjavax.xml.namespace.QNameオブジェクトをパラメタに持つコンストラクタを使用し,javax.xml.namespace.QNameオブジェクトでそのサービス(wsdl:service要素)を呼び出すのか明示的に指定してください。
スタブベースのWebサービスクライアントを開発する場合,cjwsimportコマンドを使用してWebサービスを呼び出すために必要なJavaソースを生成します。cjwsimportコマンドは,-generateServiceオプションを指定しないで実行してください。
スタブベースのWebサービスクライアントは,次のJavaソースを使用してWebサービスを呼び出します。
Webサービスクライアントの実装でWebサービスのオペレーションを呼び出す手順は,次のとおりです。
ここでは,「5.1 開発例の構成(SEI起点)」に構成を示すWebサービス(足し算をするWebサービス)を呼び出すWebサービスクライアントの実装例を示します。
Webサービスクライアントの実装に使用するクラスおよびメソッドを次の表に示します。必要に応じて,「5.5.1 サービスクラスを生成する」に記載されたサービスクラスの生成物の内容を参照してください。
表3-6 Webサービスクライアントの実装例で使用するクラスおよびメソッド
| 項番 | 種別 | クラスおよびメソッド |
|---|---|---|
| 1 | サービスクラス | AddNumbersImplService |
| 2 | SEI | AddNumbersImpl |
| 3 | SEIのメソッド | int add(int, int) |
| 4 | クライアントのメインクラス | TestClient |
デフォルトのコンストラクタを使用してサービスクラスのオブジェクトを生成する例を次に示します。
// サービスクラスをインスタンス化する AddNumbersImplService service = new AddNumbersImplService(); |
この場合,cjwsimportコマンドの引数または-wsdllocationオプションに指定したWSDLが参照されます。
cjwsimportコマンドの実行時に-wsdllocationオプションを指定しなかった場合の三つの例を次に示します。
> "%COSMINEXUS_HOME%\jaxws\bin\cjwsimport.bat" D:\dev\development.wsdl |
> D: > cd D:\dev\ > "%COSMINEXUS_HOME%\jaxws\bin\cjwsimport.bat" relative\development.wsdl |
> "%COSMINEXUS_HOME%\jaxws\bin\cjwsimport.bat" http://sample.com/fromjava/AddNumbersImplService?wsdl |
次に,cjwsimportコマンドの実行時に-wsdllocationオプションを指定した場合の二つの例を示します。
> "%COSMINEXUS_HOME%\jaxws\bin\cjwsimport.bat" -wsdllocation file:/home/wsdl4runtime/master.wsdl D:\dev\development.wsdl |
> "%COSMINEXUS_HOME%\jaxws\bin\cjwsimport.bat" -wsdllocation ./wsdl4runtime/master.wsdl D:\dev\development.wsdl |
なお,デフォルトのコンストラクタではなく,java.net.URLオブジェクトおよびjavax.xml.namespace.QNameオブジェクトをパラメタに持つコンストラクタを使用する場合は,次の例のようになります。
// サービスクラスをインスタンス化する java.net.URL wsdlLocation = new java.io.File( "./wsdl4runtime/master.wsdl" ).toURL(); javax.xml.namespace.QName serviceName = new javax.xml.namespace.QName( "http:/sample.com/", "AddNumbersImplService"); AddNumbersImplService service = new AddNumbersImplService( wsdlLocation, serviceName ); |
java.net.URLオブジェクトで指定したURLのWSDLが参照されるため,cjwsimportコマンドの引数や-wsdllocationオプションで指定したWSDLは,Webサービスクライアント実行時には存在しない,または参照できない状態でも問題ありません。ただし,Webサービスクライアント実行時のカレントディレクトリを<実行時カレントディレクトリ>とした場合は,<実行時カレントディレクトリ>/wsdl4runtime/master.wsdlが存在し,参照できる状態である必要があります。
インスタンス化したサービスクラスからポートを取得する例を次に示します。
// ポートを取得する AddNumbersImpl port = service.getAddNumbersImplPort(); |
インスタンス化したサービスクラスから取得したポートのメソッドを呼び出す例を次に示します。
// ポートのメソッドを呼び出す int returnValue = port.add(205, 103) |
この例では,ポートのメソッドの引数に二つの値を渡すと,Webサービスで足し算の処理が行われます。戻り値として足し算の演算結果が返されます。
接続するWebサービスのURL(エンドポイントアドレス)は,デフォルトでは,WSDLのポート(wsdl:port要素)が持つアドレス情報(soap:address子要素のlocation属性)が利用されます。ただし,メッセージコンテキストのjavax.xml.ws.service.endpoint.addressプロパティを利用すると,エンドポイントアドレスを動的に変更できます。
エンドポイントアドレスを動的に変更しない場合,参照されるWSDLのsoap:address子要素のlocation属性に,WebサービスクライアントからアクセスできるURLが記述されているかどうか確認してください。
エンドポイントアドレスを動的に変更する場合,ポートのメソッドを呼び出す前に要求コンテキストを取得し,javax.xml.ws.service.endpoint.addressプロパティの値を変更します。例を次に示します。
// 要求コンテキストを取得する java.util.Map<String, Object> context = ( ( javax.xml.ws.BindingProvider )port ).getRequestContext(); // エンドポイントアドレスを変更する // (javax.xml.ws.BindingProvider.ENDPOINT_ADDRESS_PROPERTYは // "javax.xml.ws.service.endpoint.address"を定義した定数) context.put( javax.xml.ws.BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://other.remote.org/fromjava/AddNumbersImplService" ); // ポートのメソッドを呼び出す int returnValue = port.add(205, 103) |
// サービスクラスをインスタンス化する
AddNumbersImplService service = new AddNumbersImplService();
// ポートを取得する
AddNumbersImpl port = service.getAddNumbersImplPort();
// ポートのメソッドを複数回呼び出す
for (int i = 0; i < 10; i++) {
int returnValue = port.add(i, i);
}
|
JavaアプリケーションのWebサービスクライアントから,サービスクラスを使用してWebサービスを呼び出す処理を実装します。
ここでは,「5.1 開発例の構成(SEI起点)」に構成を示すWebサービス(足し算をするWebサービス)を呼び出すWebサービスクライアントの実装例を示します。Webサービスクライアントの実装に使用するクラスおよびメソッドを次の表に示します。必要に応じて,「5.5.1 サービスクラスを生成する」に記載されたサービスクラスの生成物の内容を参照してください。
表3-7 Webサービスクライアントの実装例で使用するクラスおよびメソッド(JavaアプリケーションのWebサービスクライアントの場合)
| 項番 | 種別 | クラスおよびメソッド |
|---|---|---|
| 1 | サービスクラス | AddNumbersImplService |
| 2 | ポート | AddNumbersImpl |
| 3 | ポートのメソッド | int add(int, int) |
| 4 | Webサービスクライアントのクライアントのメインクラス | TestClient |
Javaアプリケーションの実装例を次に示します。
package com.example.sample.client;
import com.example.sample.AddNumbersImplTestJaxWs;
import com.example.sample.AddNumbersImplTestJaxWsService;
import com.sample.AddNumbersFault_Exception;
// Sample implementation of web service's client
public class TestClient {
public static void main( String[] args ) {
try {
// サービスクラスをインスタンス化する
AddNumbersImplTestJaxWsService service = new AddNumbersImplTestJaxWsService();
// ポートを取得する
AddNumbersImplTestJaxWs port = service.getAddNumbersImplPortTestJaxWs();
// ポートのメソッドを呼び出す
port.jaxWsTest1( ... );
int number1 = 205;
int number2 = 103;
int returnValue = port.add(number1, number2);
// 結果を表示する
System.out.println( "[RESULT] " + number1 + " + " + number2 + " = " + returnValue );
}
catch( Exception e ){
// 例外処理(ここでは単にスタックトレースを出力)
e.printStackTrace();
}
}
}
|
プログラムの実行結果を次に示します。
[RESULT] 205 + 103 = 308 |
サーブレット形態のWebサービスクライアントから,サービスクラスを使用してWebサービスを呼び出す処理を実装します。
ここでは,「5.1 開発例の構成(SEI起点)」に構成を示すWebサービス(足し算をするWebサービス)を呼び出すWebサービスクライアントの実装例を示します。Webサービスクライアントの実装に使用するクラスおよびメソッドを次の表に示します。必要に応じて,「5.5.1 サービスクラスを生成する」に記載されたサービスクラスの生成物の内容を参照してください。
表3-8 Webサービスクライアントの実装例で使用するクラスおよびメソッド(サーブレットから呼び出す場合)
| 項番 | 種別 | クラスおよびメソッド |
|---|---|---|
| 1 | サービスクラス | AddNumbersImplService |
| 2 | ポート | AddNumbersImpl |
| 3 | ポートのメソッド | int add(int, int) |
| 4 | Webサービスクライアントとなるサーブレット実装クラス | TestClient |
サーブレットからWebサービスを呼び出す実装では,サービスクラスおよびポートをサーブレットのメンバ変数として保持し,初期化します。
サービスクラスのインスタンス化およびポートの初期化の例を次に示します。
...
public class TestClient extends HttpServlet {
AddNumbersImplService service;
AddNumbersImpl port;
@Override
public void init() {
// サービスクラスをインスタンス化する
service = new AddNumbersImplService();
// ポートを取得する
port = service.getAddNumbersImplPort();
}
...
}
|
サーブレットのメンバ変数として生成したポートを使って,メソッドを呼び出します。
メソッド呼び出しの例を次に示します。
...
public class TestClient extends HttpServlet {
AddNumbersImplService service;
AddNumbersImpl port;
...
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
int number1 = ...; // requestオブジェクトから取得した値を代入
int number2 = ...; // requestオブジェクトから取得した値を代入
// ポートのメソッドを呼び出す
int returnValue = port.add(number1, number2);
...
}
}
|
サーブレットからWebサービスを呼び出す場合の実装例の全体を次に示します。
package com.sample.client;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sample.AddNumbersFault_Exception;
import com.sample.AddNumbersImpl;
import com.sample.AddNumbersImplService;
public class TestClient extends HttpServlet {
AddNumbersImplService service;
AddNumbersImpl port;
@Override
public void init() {
// サービスクラスを初期化する
service = new AddNumbersImplService();
// ポートを取得する
port = service.getAddNumbersImplPort();
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
try {
// Invoke a method of the target web service.
int number1 = ...; // requestオブジェクトから取得した値を代入
int number2 = ...; // requestオブジェクトから取得した値を代入
// ポートのメソッドを呼び出す
int returnValue = port.add(number1, number2);
// 結果を表示する
out.println("<html><body>");
out.println("<h1>RESULT</h1>");
out.println(number1 + " + " + number2 + " = " + returnValue);
out.println("</body></html>");
} catch(AddNumbersFault_Exception e) {
// 例外処理(ここでは単に例外の詳細メッセージを出力)
out.println("<html><body>");
out.println("<h1>" + e.getMessage() + "</h1>");
out.println("</body></html>");
}
}
}
|
プログラムの実行結果を次に示します。ブラウザなどからサーブレットに接続すると実行結果が表示されます。
RESULT 205 + 103 = 308 |
All Rights Reserved. Copyright (C) 2008, 2011, Hitachi, Ltd.