非同期webサービスの解説と jax-rpcによる実装例...
TRANSCRIPT
JTC 2004 Java Session(Technology)
非同期Webサービスの解説と JAX-RPCによる実装例の紹介
2004年2月18日
株式会社NTTデータ技術開発本部
木村 利幸
Java Community Process
JSR-224 Expert Group Member
Apache Axis Committer
Toshi <[email protected]>
2
本日のAgenda
3
本日のAgenda• 背景
• 非同期Webサービスの要件
• 非同期Webサービスの技術的課題
• Axisを利用した非同期サービス実装
• 標準化動向
• 今後の展望
etc.
【セッションのキーワード】【セッションのキーワード】
非同期 非同期WebWebサービスサービス
JAXJAX--RPC ( RPC ( ver 1.0, 1.1, 2.0ver 1.0, 1.1, 2.0 ))
HTTPHTTPプロトコルプロトコル ( ( RFC 2616RFC 2616 ))
オープンソースオープンソース ( ( Apache AxisApache Axis ))
Java Message Service ( Java Message Service ( JMSJMS ))
4
本講演テーマの背景
5
背景 ー その1 -
【研究開発テーマ】
J2EE技術とWebサービス技術を活用し、 『基幹システムのオープン化』を実現する
なぜJ2EE、 Webサービスなのか?
多様な言語・プラットフォームでの既存資産対応の必要性
開発規模が膨大で、言語レベルの完全移植は至難の技
システム連携プロトコルとしてのWebサービスの定着と 基盤整備の前進(JAX-RPC, Apache Axis等)
J2EEコンポーネントの開発、負荷分散の活用
... しかし、Webサービス適用にも課題が存在する
6
背景 ー その2 -
非同期Webサービス適用範囲非同期非同期WebWebサービス適用範囲サービス適用範囲
クライアントクライアント SOAPSOAPサーバサーバ 基幹システム基幹システム((EIS)EIS)
Webサービス
Webサービス
専用プロトコル
専用プロトコル
【本講演テーマ】
非同期Webサービスの解説と JAX-RPCによる実装例の紹介
SOAP over HTTPSOAP over HTTP環境における環境における
本講演テーマと研究テーマの関係は?
7
非同期Webサービスの要件
8
非同期Webサービス
WebサービスWebサービスクライアント実装クライアント実装
処理ブロック処理ブロック
Webサービス実装Webサービス実装
クライアントクライアント SOAPSOAPサーバサーバ
まず、非同期型の前に同期型を再整理
■ 同期型Webサービス
HTTP 1HTTP 1接続接続
処理要求処理要求
結果取得結果取得
長時間処理には不向き長時間処理長時間処理には不向きには不向き
○ HTTP 1接続で完結し、サービス構築が容易
× 完了までクライアント処理がブロックされる
9
非同期Webサービス■ 非同期型Webサービスの種類
■ コールバック(Push)型
• 「処理依頼」と「結果取得」が別のHTTP接続
• 処理終了時にサーバ側から結果がPush
■ ポーリング(Pull)型
• 「処理依頼」と「結果取得」が別のHTTP接続
• 「結果取得」がクライアント側からのPolling
10
非同期Webサービスの課題
11
技術課題■ コールバック(Push)型
Webサービス実装Webサービス実装WebサービスWebサービスクライアント実装クライアント実装
ブロック時間が短いブロック時間が短いSOAPSOAPサーバサーバクライアントクライアント
処理要求処理要求
結果取得結果取得
○ クライアント・ブロック時間短縮(非同期化実現)クライアント側のサーバ化は困難
クライアント側のクライアント側のサーバ化は困難サーバ化は困難
△ HTTP 2接続で処理が完結する
× クライアント側にSOAPサーバ機能が必要!
12
技術課題■ ポーリング(Pull)型
WebサービスWebサービスクライアント実装クライアント実装 Webサービス実装Webサービス実装
ブロック時間が短いブロック時間が短いSOAPSOAPサーバサーバクライアントクライアント
処理要求処理要求
結果取得結果取得
結果取得結果取得
過負荷防止・Wait調整必要だが…
過負荷防止・過負荷防止・WaitWait調整必要調整必要だがだが…… 採用
○ クライアント・ブロック時間短縮(非同期化実現)
○ クライアント側にSOAPサーバ機能が不要!
△ クライアント側から複数回のPollingが必要!
13
非同期Webサービスの実装
14
非同期Webサービス実装
J2EE PlatformJ2EE Platform
WebWebコンテナコンテナ
クライアントクライアント SOAPSOAPサーバサーバ
JMSJMS EJBEJBコンテナコンテナ
DBMS/EIS
J2EE PlatformJ2EE Platform
※※ MDB (MessageMDB (Message--Driven Bean)Driven Bean)
※※ JMS (Java Message Service)JMS (Java Message Service)
※※ SLSB (Stateless Session Bean) SLSB (Stateless Session Bean)
MDBMDB
SLSBSLSB
Queue/
Topic
Queue/
Topic
WebサービスWebサービスクライアント実装クライアント実装
JAX-RPCJAXJAX--RPCRPCJAX-RPCJAXJAX--RPCRPC
EndEnd--pointpoint
InvokeInvokeInvoke
ID取得IDID取得取得
結果取得結果取得結果取得
ポーリング型非同期Webサービスの実現
課題1: サーバ負荷上昇の問題
課題2: クライアント実装複雑化の問題
15
非同期Webサービスの実装
課題1: サーバ負荷上昇への対策
16
非同期Webサービス実装課題1: 過剰ポーリングによるサーバ負荷上昇への対策
Webサービスの応答電文(SOAPレスポンスデータ)のキャッシュWebWebサービスの応答電文サービスの応答電文((SOAPSOAPレスポンスデータレスポンスデータ))のキャッシュのキャッシュ
HTTP Proxy(キャッシュ機構)をそのまま活用できないか?HTTP Proxy(HTTP Proxy(キャッシュ機構キャッシュ機構))をそのまま活用できないか?をそのまま活用できないか?
Hypertext Transfer Protocol - HTTP 1.1 仕様 [RFC 2616より]
9.5 POST(中略)
レスポンスが適切な Cache-Control や Expires ヘッダフィールドを含んで いなければ、このメソッドのレスポンスはキャッシュ可能ではない。 | Responses to this method are not cacheable, unless the response includes appropriate | Cache-Control or Expires header fields.
この規定であれば、ProxyサーバでSOAPキャッシュが実現可能かも!?
17
非同期Webサービス実装既存HTTP ProxyサーバでSOAPキャッシュが実現可能か!?
4
3
2
1
項番
Microsoft社Internet Security &
Accelerator Server
Yutaka Sato氏DeleGate
Squid開発者グループSquid 2 STABLE 7
Sun Microsystems社Sun ONE
Web Proxy 3.6 sp2
POST MethodGET Method
検証結果開発元名 称
○○
○○
○○
○○
××
××
××××
※※ ○○ :: キャッシュされるキャッシュされる
※※×× :: キャッシュされないキャッシュされないHTTP POSTメソッドを利用するSOAPメッセージ・キャッシュにはProxyサーバを活用できない
HTTP POSTHTTP POSTメソッドを利用するメソッドを利用するSOAPSOAPメッセージ・キャッシュにはメッセージ・キャッシュにはProxyProxyサーバを活用できないサーバを活用できない 対策は?
18
非同期Webサービス実装HTTP POSTメソッドを利用するSOAPメッセージ・キャッシュ法
SOAPサーバ側でキャッシュ制御パラメタを設定SOAPSOAPサーバ側でキャッシュ制御パラメタを設定サーバ側でキャッシュ制御パラメタを設定
SOAPクライアント側にローカルキャッシュ機構を構築SOAPSOAPクライアント側にローカルキャッシュ機構を構築クライアント側にローカルキャッシュ機構を構築
既存ソフトウェアの設定のみでは対処不可能でありJAX-RPC実行環境に改変を加える必要がある
オープンソースのJAX-RPC実行環境である
Apache Axisを採用したフィージビリティ・スタディ実施
19
通信部通信部
同期同期APIAPI
クライアントクライアントAPAP
通信部通信部
SOAPサーバSOAPサーバ
WebWebサービスサービス
J2EE Platform
拡張部拡張部既存部既存部【凡例】
SOAPSOAPクライアントクライアント
AXISAXISAXISAXIS
キャッシュ対応キャッシュ対応
キャッシュキャッシュ制御部制御部
APIAPI
ローカルキャッシュローカルキャッシュ
キャッシュキャッシュ制御部制御部
APIAPI
SOAPメッセージ・キャッシュ機構のアーキテクチャ
非同期Webサービス実装
20
非同期Webサービス実装SOAPキャッシュ機構のフィージビリ・スタディ - 1
キャッシュが有効なモデル定義
天気予報サービス(WeatherForecastService)
【ソースコード例】 WeatherForecastService Interface
package com.example;
public interface WeatherForecastProvider extends java.rmi.Remote { int getChanceOfRain ( String areaSymbol ) throws java.rmi.RemoteException; // …}
指定されたエリアの降水確率の予想値を返しますその予想は、3時間おきに更新される計測データから予想されます降水確率の値は、クライアントが頻繁にアクセスした場合でも、次の計測値が更新されるまでの間は、変化がありません
WeatherForecast WeatherForecast ServiceService
観測データ
予測予測
観測装置観測装置
3時間毎のデータ収集
21
非同期Webサービス実装SOAPキャッシュ機構のフィージビリ・スタディ - 2
キャッシュ可能モデルの実装事例
WebWebBrowserBrowser
SOAPSOAPクライアントクライアントAPAP
AXISAXIS
ServletServlet
SOAPサーバSOAPサーバSOAPSOAPクライアントクライアント
HTTPHTTPHeaderHeaderHandlerHandler
天気予報天気予報WebWebサービスサービス
AXISAXIS
ローカルキャッシュローカルキャッシュ
J2EE PlatformJ2EE PlatformJ2EE PlatformJ2EE Platform
OKOK東京名古屋
大阪
降水確率は60% です
初回アクセス初回アクセス初回アクセス
次回アクセス次回アクセス次回アクセス
22
非同期Webサービスの実装
課題2: クライアント実装の複雑化への対策
23
非同期Webサービス実装課題2: クライアント実装の複雑化への対策
J2EE PlatformJ2EE Platform
WebWebコンテナコンテナ
クライアントクライアント SOAPSOAPサーバサーバ
JMSJMS EJBEJBコンテナコンテナ
DBMS/EIS
J2EE PlatformJ2EE Platform
WebサービスWebサービスクライアント実装クライアント実装
JAX-RPCJAXJAX--RPCRPCJAX-RPCJAXJAX--RPCRPC
MDBMDB
SLSBSLSB
TopicTopic
EndEnd--pointpointInvokeInvokeInvoke
ID取得IDID取得取得
結果取得結果取得結果取得
試行・ウエイト・終了判定試行・ウエイト・終了判定処理の繰り返し処理の繰り返し
複雑なポーリング処理を隠蔽し、クライアント実装を簡略化複雑なポーリング処理を隠蔽し、クライアント実装を簡略化複雑なポーリング処理を隠蔽し、クライアント実装を簡略化
24
非同期Webサービス実装複雑なポーリング処理を隠蔽し、クライアント実装を簡略化
クライアントクライアント
J2EE PlatformJ2EE Platform
WebサービスWebサービスクライアント実装クライアント実装
JAX-RPCJAXJAX--RPCRPC
SOAPSOAPサーバサーバ
J2EE PlatformJ2EE Platform
JAX-RPCJAXJAX--RPCRPC
Webサービス実装Webサービス実装
ユーティリティ部ユーティリティ部
InvokeInvokeInvoke
結果取得結果取得結果取得
同期
同期
//非
同期
共通
非同
期共
通IFIF
制御部制御部
タイマタイマ管理部管理部
制御情報制御情報管理部管理部
実行状態管理部実行状態管理部
25
非同期Webサービス実装ユーティリティ適用の効果 - 1
//処理要求用の設定
Servcie service = new Service(serviceName);
Call call = service.createCall();
call.setOperationName(startOperationName);
call.addParameter("in0", XMLType.XSD_STRING,ParameterMode.IN);
call.addParameter("in1", XMLType.XSD_LONG,ParameterMode.IN);
call.setReturnType(XSD_ANY);
call.setTargetEndpointAddress(endpointURL);
call.setMaintainSession(true);
call.invoke(new Object[]{"HELLO", new Integer(10)});//処理要求呼び出し
//パーサの準備
try{
DocumentBuilderFactory d = DocumentBuilderFactory.newInstance();
DocumentBuilderFactory factory = new org.apache.xerces.jaxp.DocumentBuilderFactoryImpl();
boolean isValidate = true;
factory.setValidating(isValidate);
factory.setNamespaceAware(true);
factory.setAttribute("http://apache.org/xml/features/validation/schema" ,new Boolean(true));
builder = factory.newDocumentBuilder();
builder.setErrorHandler(new ValidationErrorHandler());
}catch(ParserConfigurationException e){
throw new InternalException(e);
}
//ヘッダ要素の抽出開始
MessageContext msgContext = call.getMessageContext();
Message msg = (Message)msgContext.getMessage();
SOAPEnvelope envelope = msg.getSOAPEnvelope();
SOAPHeaderElement asyncSOAPHeader = envelope.getHeaderByName(Constants.ASYNCSOAP_NS,Constants.ASYNCSOAPHEADER_LOCAL);
MessageElement asyncSOAPElement = (MessageElement)asyncSOAPHeader.getChildren().get(0);
Document headerDoc = asyncSOAPElement.getAsDocument();
String headerString = new XMLUtils().DocumentToString(headerDoc);
ByteArrayInputStream headerStream = new ByteArrayInputStream(headerString.getBytes());
builder.parse(headerStream);//パース
headerStream.close();
//ステータスを取得
Element asyncServerStatusElement = (Element)headerDoc.getElementsByTagNameNS(Constants.ASYNCSOAP_NS, Constants.ASYNCSERVERSTATUS_LOCAL).item(0);
Element asyncWorkflowElement =(Element)headerDoc.getElementsByTagNameNS(Constants.ASYNCSOAP_NS, Constants.ASYNCWORKFLOW_LOCAL).item(0);
String statusCode = asyncServerStatusElement.getElementsByTagName(Constants.STATUSCODE_LOCAL).item(0).getFirstChild().getNodeValue();
String statusString = asyncServerStatusElement.getElementsByTagName(Constants.STATUSSTRING_LOCAL).item(0).getFirstChild().getNodeValue();
Element detail = (Element)asyncServerStatusElement.getElementsByTagName(Constants.DETAIL_LOCAL).item(0);
NodeList asyncStaticParamNodeList = headerDoc.getElementsByTagName(Constants.ASYNCSTATICPARAM_LOCAL);
//静的パラメータを取得
Element asyncStaticParamElement = (Element)asyncStaticParamNodeList.item(0);
Text firstIntervalText = (Text)asyncStaticParamElement.getElementsByTagName(Constants.FIRSTINTERVAL_LOCAL).item(0).getFirstChild();
long firstInterval = Long.parseLong(firstIntervalText.getNodeValue());
Text iterateIntervalText = (Text)asyncStaticParamElement.getElementsByTagName(Constants.ITERATEINTERVAL_LOCAL).item(0).getFirstChild();
long iterateInterval = Long.parseLong(iterateIntervalText.getNodeValue());
Text timeoutIntervalText = (Text)asyncStaticParamElement.getElementsByTagName(Constants.TIMEOUTINTERVAL_LOCAL).item(0).getFirstChild();
long timeoutInterval = Long.parseLong(timeoutIntervalText.getNodeValue());
Text maxRetryCountText = (Text)asyncStaticParamElement.getElementsByTagName(Constants.MAXRETRYCOUNT_LOCAL).item(0).getFirstChild();
int maxRetryCount = Integer.parseInt(maxRetryCountText.getNodeValue());
//ポーリング用の準備
Call pollingCall = service.createCall();
pollingCall.setOperationName(endOperationName);
pollingCall.setReturnType(XSD_STRING);
//第一回目のポーリングまで待機
Thread.sleep(firstInterval * 1000);//待機
//ポーリングのループ開始
boolean completed = false;//処理完了フラグ
int loop_count = 0;
while(completed){//処理が完了するまでループ
Object ret = pollingCall.invoke(new Object[]{"HELLO", new Integer(10)});//結果確認呼び出し
loop_count++;
//ヘッダ要素の抽出開始
MessageContext msgContext = call.getMessageContext();
Message msg = (Message)msgContext.getMessage();
SOAPEnvelope envelope = msg.getSOAPEnvelope();
SOAPHeaderElement asyncSOAPHeader = envelope.getHeaderByName(Constants.ASYNCSOAP_NS,Constants.ASYNCSOAPHEADER_LOCAL);
MessageElement asyncSOAPElement = (MessageElement)asyncSOAPHeader.getChildren().get(0);
Document headerDoc = asyncSOAPElement.getAsDocument();
String headerString = new XMLUtils().DocumentToString(headerDoc);
ByteArrayInputStream headerStream = new ByteArrayInputStream(headerString.getBytes());
builder.parse(headerStream);
headerStream.close();
//パラメータの抽出
Element asyncServerStatusElement = (Element)headerDoc.getElementsByTagNameNS(Constants.ASYNCSOAP_NS, Constants.ASYNCSERVERSTATUS_LOCAL).item(0);
Element asyncWorkflowElement =(Element)headerDoc.getElementsByTagNameNS(Constants.ASYNCSOAP_NS, Constants.ASYNCWORKFLOW_LOCAL).item(0);
String statusCode = asyncServerStatusElement.getElementsByTagName(Constants.STATUSCODE_LOCAL).item(0).getFirstChild().getNodeValue();
String statusString = asyncServerStatusElement.getElementsByTagName(Constants.STATUSSTRING_LOCAL).item(0).getFirstChild().getNodeValue();
Element detail = (Element)asyncServerStatusElement.getElementsByTagName(Constants.DETAIL_LOCAL).item(0);
//ステータスの確認
if(!statusCode.equals("RUNNING")){
completed = true;
}
//最大リトライ数のチェック
if(loop_count >= maxRetryCount){
throw new Exception("最大ポーリング回数を超過しました.");
}
Thread.sleep(iterateInterval * 1000);
}
//結果の表示
System.out.println("return : " + ret);
//処理要求用の設定
Servcie service = new Service(serviceName);
Call call = service.createCall();
call.setOperationName(startOperationName);
call.addParameter("in0", XMLType.XSD_STRING,ParameterMode.IN);
call.addParameter("in1", XMLType.XSD_LONG,ParameterMode.IN);
call.setReturnType(XSD_ANY);
call.setTargetEndpointAddress(endpointURL);
call.setMaintainSession(true);
call.invoke(new Object[]{"HELLO", new Integer(10)});//処理要求呼び出し
//パーサの準備
try{
DocumentBuilderFactory d = DocumentBuilderFactory.newInstance();
DocumentBuilderFactory factory = new org.apache.xerces.jaxp.DocumentBuilderFactoryImpl();
boolean isValidate = true;
factory.setValidating(isValidate);
factory.setNamespaceAware(true);
factory.setAttribute("http://apache.org/xml/features/validation/schema" ,new Boolean(true));
builder = factory.newDocumentBuilder();
builder.setErrorHandler(new ValidationErrorHandler());
}catch(ParserConfigurationException e){
throw new InternalException(e);
}
//ヘッダ要素の抽出開始
MessageContext msgContext = call.getMessageContext();
Message msg = (Message)msgContext.getMessage();
SOAPEnvelope envelope = msg.getSOAPEnvelope();
SOAPHeaderElement asyncSOAPHeader = envelope.getHeaderByName(Constants.ASYNCSOAP_NS,Constants.ASYNCSOAPHEADER_LOCAL);
MessageElement asyncSOAPElement = (MessageElement)asyncSOAPHeader.getChildren().get(0);
Document headerDoc = asyncSOAPElement.getAsDocument();
String headerString = new XMLUtils().DocumentToString(headerDoc);
ByteArrayInputStream headerStream = new ByteArrayInputStream(headerString.getBytes());
builder.parse(headerStream);//パース
headerStream.close();
//ステータスを取得
Element asyncServerStatusElement = (Element)headerDoc.getElementsByTagNameNS(Constants.ASYNCSOAP_NS, Constants.ASYNCSERVERSTATUS_LOCAL).item(0);
Element asyncWorkflowElement =(Element)headerDoc.getElementsByTagNameNS(Constants.ASYNCSOAP_NS, Constants.ASYNCWORKFLOW_LOCAL).item(0);
String statusCode = asyncServerStatusElement.getElementsByTagName(Constants.STATUSCODE_LOCAL).item(0).getFirstChild().getNodeValue();
String statusString = asyncServerStatusElement.getElementsByTagName(Constants.STATUSSTRING_LOCAL).item(0).getFirstChild().getNodeValue();
Element detail = (Element)asyncServerStatusElement.getElementsByTagName(Constants.DETAIL_LOCAL).item(0);
NodeList asyncStaticParamNodeList = headerDoc.getElementsByTagName(Constants.ASYNCSTATICPARAM_LOCAL);
//静的パラメータを取得
Element asyncStaticParamElement = (Element)asyncStaticParamNodeList.item(0);
Text firstIntervalText = (Text)asyncStaticParamElement.getElementsByTagName(Constants.FIRSTINTERVAL_LOCAL).item(0).getFirstChild();
long firstInterval = Long.parseLong(firstIntervalText.getNodeValue());
Text iterateIntervalText = (Text)asyncStaticParamElement.getElementsByTagName(Constants.ITERATEINTERVAL_LOCAL).item(0).getFirstChild();
long iterateInterval = Long.parseLong(iterateIntervalText.getNodeValue());
Text timeoutIntervalText = (Text)asyncStaticParamElement.getElementsByTagName(Constants.TIMEOUTINTERVAL_LOCAL).item(0).getFirstChild();
long timeoutInterval = Long.parseLong(timeoutIntervalText.getNodeValue());
Text maxRetryCountText = (Text)asyncStaticParamElement.getElementsByTagName(Constants.MAXRETRYCOUNT_LOCAL).item(0).getFirstChild();
int maxRetryCount = Integer.parseInt(maxRetryCountText.getNodeValue());
//ポーリング用の準備
Call pollingCall = service.createCall();
pollingCall.setOperationName(endOperationName);
pollingCall.setReturnType(XSD_STRING);
//第一回目のポーリングまで待機
Thread.sleep(firstInterval * 1000);//待機
//ポーリングのループ開始
boolean completed = false;//処理完了フラグ
int loop_count = 0;
while(completed){//処理が完了するまでループ
Object ret = pollingCall.invoke(new Object[]{"HELLO", new Integer(10)});//結果確認呼び出し
loop_count++;
//ヘッダ要素の抽出開始
MessageContext msgContext = call.getMessageContext();
Message msg = (Message)msgContext.getMessage();
SOAPEnvelope envelope = msg.getSOAPEnvelope();
SOAPHeaderElement asyncSOAPHeader = envelope.getHeaderByName(Constants.ASYNCSOAP_NS,Constants.ASYNCSOAPHEADER_LOCAL);
MessageElement asyncSOAPElement = (MessageElement)asyncSOAPHeader.getChildren().get(0);
Document headerDoc = asyncSOAPElement.getAsDocument();
String headerString = new XMLUtils().DocumentToString(headerDoc);
ByteArrayInputStream headerStream = new ByteArrayInputStream(headerString.getBytes());
builder.parse(headerStream);
headerStream.close();
//パラメータの抽出
Element asyncServerStatusElement = (Element)headerDoc.getElementsByTagNameNS(Constants.ASYNCSOAP_NS, Constants.ASYNCSERVERSTATUS_LOCAL).item(0);
Element asyncWorkflowElement =(Element)headerDoc.getElementsByTagNameNS(Constants.ASYNCSOAP_NS, Constants.ASYNCWORKFLOW_LOCAL).item(0);
String statusCode = asyncServerStatusElement.getElementsByTagName(Constants.STATUSCODE_LOCAL).item(0).getFirstChild().getNodeValue();
String statusString = asyncServerStatusElement.getElementsByTagName(Constants.STATUSSTRING_LOCAL).item(0).getFirstChild().getNodeValue();
Element detail = (Element)asyncServerStatusElement.getElementsByTagName(Constants.DETAIL_LOCAL).item(0);
//ステータスの確認
if(!statusCode.equals("RUNNING")){
completed = true;
}
//最大リトライ数のチェック
if(loop_count >= maxRetryCount){
throw new Exception("最大ポーリング回数を超過しました.");
}
Thread.sleep(iterateInterval * 1000);
}
//結果の表示
System.out.println("return : " + ret);
利用しない場合利用しない場合
// ポーリングによる実装例
ServiceFactory factory = ServiceFactory.newInstance();
Service service = ServiceFactory.createService(serviceName);
Call call = service.createCall();
call.setOperationName(new QName(targetNS, operationName));
call.setTargetEndpointAddress(endpointURL);
call.addParameter("in0", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter("in1", XMLType.XSD_LONG, ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);
call.setOperationModel(OperationModel.ASYNC_PULL);
call.invokeAsync(new Object[]{inputData});
long pollingInterval = 2000;
AsyncStatus status = call.getAsyncStatus();
while(status.isRunnging()){
Thread.sleep(pollingInterval);
status = call.getAsyncStatus();
}
String ret = (String)call.getAsyncReturnValue();
System.out.println(ret);
// ポーリングによる実装例
ServiceFactory factory = ServiceFactory.newInstance();
Service service = ServiceFactory.createService(serviceName);
Call call = service.createCall();
call.setOperationName(new QName(targetNS, operationName));
call.setTargetEndpointAddress(endpointURL);
call.addParameter("in0", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter("in1", XMLType.XSD_LONG, ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);
call.setOperationModel(OperationModel.ASYNC_PULL);
call.invokeAsync(new Object[]{inputData});
long pollingInterval = 2000;
AsyncStatus status = call.getAsyncStatus();
while(status.isRunnging()){
Thread.sleep(pollingInterval);
status = call.getAsyncStatus();
}
String ret = (String)call.getAsyncReturnValue();
System.out.println(ret);
利用した場合利用した場合
実行行数: 75実行行数: 75実行行数: 17実行行数: 17
約4.5倍、ユーザ実装量を減少約約4.54.5倍倍、ユーザ実装量を減少、ユーザ実装量を減少
26
非同期Webサービス実装ユーティリティ適用の効果 - 2
同期
同期
//非
同期
共通
非同
期共
通IFIF
クライアントクライアント
WebサービスWebサービスクライアント実装クライアント実装 JAXJAX--RPC 1.0, 1.1RPC 1.0, 1.1規定済み規定済み
Call . Invoke ()Call . Invoke ()Call . Invoke ()
Call . invokeOneWay ()Call . invokeOneWay ()Call . invokeOneWay ()
{ Call . invokeAsync () } ?{ { Call . invokeAsync () Call . invokeAsync () } ?} ?
JAXJAX--RPC 2.0RPC 2.0規定範囲規定範囲((議論中議論中))
同期呼び出し同期呼び出し同期呼び出し
一方向呼び出し一方向呼び出し一方向呼び出し
非同期呼び出し非同期呼び出し非同期呼び出し
既存の同期型APIに準ずる用法で非同期呼び出しが可能既存の同期型既存の同期型APIAPIに準ずる用法で非同期呼び出しが可能に準ずる用法で非同期呼び出しが可能
27
非同期Webサービス実装ユーティリティ適用の効果 - 3
クライアントクライアント SOAPSOAPサーバサーバ
Webサービス実装Webサービス実装Webサービスクライアント実装Webサービスクライアント実装
同期
同期
//非
同期
共通
非同
期共
通IFIF
同期型API同期型同期型APIAPI
コールバック型APIコールバック型コールバック型APIAPI
ポーリング型APIポーリング型ポーリング型APIAPI
同期型WS同期型同期型WSWS
ポーリング型WSポーリング型ポーリング型WSWS
API層、トランスポート層のアクセス・モデルを完全分離APIAPI層、トランスポート層のアクセス・モデルを完全分離層、トランスポート層のアクセス・モデルを完全分離
28
クライアントクライアント SOAPSOAPサーバサーバ
Webサービス実装Webサービス実装Webサービスクライアント実装Webサービスクライアント実装
ユーティリティ部 ユーティリティ部
ポーリング型WSポーリング型ポーリング型WSWS
制御情報DB
AA
BBCC
非同期Webサービス実装ユーティリティ適用の効果 - 4
処理要求処理要求
結果取得結果取得
<<asyncWorkflow> asyncWorkflow> <asyncStaticParam><asyncStaticParam>
<firstInteval><firstInteval>36003600</firstInterval></firstInterval> <iterateInterval><iterateInterval>360360</iterateInterval></iterateInterval>
<timeoutInterval><timeoutInterval>100000100000</timeoutInterval></timeoutInterval><maxRetryCount>50</maxRetryCount><maxRetryCount>50</maxRetryCount>
</asyncStaticParam></asyncStaticParam><asyncWorkflow><asyncWorkflow>
サーバ負荷制御、ポーリング・タイミング制御の実現サーバ負荷制御、ポーリング・タイミング制御の実現サーバ負荷制御、ポーリング・タイミング制御の実現
29
対策のまとめ
30
J2EEJ2EE PlatformPlatform
通信部通信部
同期同期APIAPI
クライアントクライアントAPAP
通信部通信部
WebWebサービスサービス
AXISAXISAXISAXIS
クライアントクライアント SOAPSOAPサーバサーバ
非同期Webサービス実装
キャッシュ対応キャッシュ対応
非同期対応非同期対応
非同期対応後のJAX-RPCアーキテクチャ
キャッシュキャッシュ制御部制御部
APIAPI
ローカルキャッシュローカルキャッシュ
キャッシュキャッシュ制御部制御部
APIAPI非同期非同期APIAPI
ワークフローワークフロー制御部制御部
31
標準化動向
32
標準化動向
非同期Webサービスに関して
JAX-RPC ver 1.1仕様の後継仕様であるJAX-RPC ver 2.0となるJSR-224 Expert Groupメンバ内でAPIを検討中
※ 現時点では、同カテゴリについて明確な決定がなされていません ※ 2004年3月上旬に、Expert GroupのFace-to-Faceの会議が計画されています
キャッシュ制御に関して
本日の講演で紹介した内容をApache Axis公式サイトで公開し、コメントを収集中
[ URL ] <http://ws.apache.org/axis/docs/CachingEarlDraft2.html>
※ 現在、英語版のみの公開です ※ 日本語版をご希望の方は、メールでご連絡ください
33
ー The End -
Any Questions ?
本資料で利用される、Sun, Sun Microsystems, Java, J2EEなどの語句は、Sun Microsystems 社殿の商標もしくは登録商標です。また、それ以外の製品名等は一般的にそれら各企業の商標ですが、表示を省略しています。