非同期webサービスの解説と jax-rpcによる実装例...

33
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]>

Upload: others

Post on 08-Apr-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

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]>

Page 2: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

2

本日のAgenda

Page 3: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

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 ))

Page 4: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

4

本講演テーマの背景

Page 5: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

5

背景 ー その1 -

【研究開発テーマ】

  J2EE技術とWebサービス技術を活用し、  『基幹システムのオープン化』を実現する

なぜJ2EE、 Webサービスなのか?

多様な言語・プラットフォームでの既存資産対応の必要性

開発規模が膨大で、言語レベルの完全移植は至難の技

システム連携プロトコルとしてのWebサービスの定着と  基盤整備の前進(JAX-RPC, Apache Axis等)

J2EEコンポーネントの開発、負荷分散の活用

... しかし、Webサービス適用にも課題が存在する

Page 6: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

6

背景 ー その2 -

非同期Webサービス適用範囲非同期非同期WebWebサービス適用範囲サービス適用範囲

クライアントクライアント SOAPSOAPサーバサーバ 基幹システム基幹システム((EIS)EIS)

Webサービス

Webサービス

専用プロトコル

専用プロトコル

【本講演テーマ】

非同期Webサービスの解説と    JAX-RPCによる実装例の紹介

SOAP over HTTPSOAP over HTTP環境における環境における

本講演テーマと研究テーマの関係は?

Page 7: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

7

非同期Webサービスの要件

Page 8: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

8

非同期Webサービス

WebサービスWebサービスクライアント実装クライアント実装

処理ブロック処理ブロック

Webサービス実装Webサービス実装

クライアントクライアント SOAPSOAPサーバサーバ

まず、非同期型の前に同期型を再整理

■ 同期型Webサービス

HTTP 1HTTP 1接続接続

処理要求処理要求

結果取得結果取得

長時間処理には不向き長時間処理長時間処理には不向きには不向き

○ HTTP 1接続で完結し、サービス構築が容易

× 完了までクライアント処理がブロックされる

Page 9: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

9

非同期Webサービス■ 非同期型Webサービスの種類

■ コールバック(Push)型

• 「処理依頼」と「結果取得」が別のHTTP接続

• 処理終了時にサーバ側から結果がPush

■ ポーリング(Pull)型

• 「処理依頼」と「結果取得」が別のHTTP接続

• 「結果取得」がクライアント側からのPolling

Page 10: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

10

非同期Webサービスの課題

Page 11: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

11

技術課題■ コールバック(Push)型

Webサービス実装Webサービス実装WebサービスWebサービスクライアント実装クライアント実装

ブロック時間が短いブロック時間が短いSOAPSOAPサーバサーバクライアントクライアント

処理要求処理要求

結果取得結果取得

○ クライアント・ブロック時間短縮(非同期化実現)クライアント側のサーバ化は困難

クライアント側のクライアント側のサーバ化は困難サーバ化は困難

△ HTTP 2接続で処理が完結する

× クライアント側にSOAPサーバ機能が必要!

Page 12: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

12

技術課題■ ポーリング(Pull)型

WebサービスWebサービスクライアント実装クライアント実装 Webサービス実装Webサービス実装

ブロック時間が短いブロック時間が短いSOAPSOAPサーバサーバクライアントクライアント

処理要求処理要求

結果取得結果取得

結果取得結果取得

過負荷防止・Wait調整必要だが…

過負荷防止・過負荷防止・WaitWait調整必要調整必要だがだが…… 採用

○ クライアント・ブロック時間短縮(非同期化実現)

○ クライアント側にSOAPサーバ機能が不要!

△ クライアント側から複数回のPollingが必要!

Page 13: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

13

非同期Webサービスの実装

Page 14: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期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: クライアント実装複雑化の問題

Page 15: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

15

非同期Webサービスの実装

課題1: サーバ負荷上昇への対策

Page 16: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

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キャッシュが実現可能かも!?

Page 17: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

17

非同期Webサービス実装既存HTTP ProxyサーバでSOAPキャッシュが実現可能か!?

項番

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サーバを活用できないサーバを活用できない 対策は?

Page 18: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

18

非同期Webサービス実装HTTP POSTメソッドを利用するSOAPメッセージ・キャッシュ法

SOAPサーバ側でキャッシュ制御パラメタを設定SOAPSOAPサーバ側でキャッシュ制御パラメタを設定サーバ側でキャッシュ制御パラメタを設定

SOAPクライアント側にローカルキャッシュ機構を構築SOAPSOAPクライアント側にローカルキャッシュ機構を構築クライアント側にローカルキャッシュ機構を構築

既存ソフトウェアの設定のみでは対処不可能でありJAX-RPC実行環境に改変を加える必要がある

オープンソースのJAX-RPC実行環境である 

Apache Axisを採用したフィージビリティ・スタディ実施

Page 19: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

19

通信部通信部

同期同期APIAPI

クライアントクライアントAPAP

通信部通信部

SOAPサーバSOAPサーバ

WebWebサービスサービス

J2EE Platform

拡張部拡張部既存部既存部【凡例】

SOAPSOAPクライアントクライアント

AXISAXISAXISAXIS

キャッシュ対応キャッシュ対応

キャッシュキャッシュ制御部制御部

APIAPI

ローカルキャッシュローカルキャッシュ

キャッシュキャッシュ制御部制御部

APIAPI

SOAPメッセージ・キャッシュ機構のアーキテクチャ

非同期Webサービス実装

Page 20: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期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時間毎のデータ収集

Page 21: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

21

非同期Webサービス実装SOAPキャッシュ機構のフィージビリ・スタディ - 2

キャッシュ可能モデルの実装事例

WebWebBrowserBrowser

SOAPSOAPクライアントクライアントAPAP

AXISAXIS

ServletServlet

SOAPサーバSOAPサーバSOAPSOAPクライアントクライアント

HTTPHTTPHeaderHeaderHandlerHandler

天気予報天気予報WebWebサービスサービス

AXISAXIS

ローカルキャッシュローカルキャッシュ

J2EE PlatformJ2EE PlatformJ2EE PlatformJ2EE Platform

OKOK東京名古屋

大阪

降水確率は60% です

初回アクセス初回アクセス初回アクセス

次回アクセス次回アクセス次回アクセス

Page 22: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

22

非同期Webサービスの実装

課題2: クライアント実装の複雑化への対策

Page 23: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

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取得取得

結果取得結果取得結果取得

試行・ウエイト・終了判定試行・ウエイト・終了判定処理の繰り返し処理の繰り返し

複雑なポーリング処理を隠蔽し、クライアント実装を簡略化複雑なポーリング処理を隠蔽し、クライアント実装を簡略化複雑なポーリング処理を隠蔽し、クライアント実装を簡略化

Page 24: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

24

非同期Webサービス実装複雑なポーリング処理を隠蔽し、クライアント実装を簡略化

クライアントクライアント

J2EE PlatformJ2EE Platform

WebサービスWebサービスクライアント実装クライアント実装

JAX-RPCJAXJAX--RPCRPC

SOAPSOAPサーバサーバ

J2EE PlatformJ2EE Platform

JAX-RPCJAXJAX--RPCRPC

Webサービス実装Webサービス実装

ユーティリティ部ユーティリティ部

InvokeInvokeInvoke

結果取得結果取得結果取得

同期

同期

//非

同期

共通

非同

期共

通IFIF

制御部制御部

タイマタイマ管理部管理部

制御情報制御情報管理部管理部

実行状態管理部実行状態管理部

Page 25: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

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倍倍、ユーザ実装量を減少、ユーザ実装量を減少

Page 26: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

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に準ずる用法で非同期呼び出しが可能に準ずる用法で非同期呼び出しが可能

Page 27: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

27

非同期Webサービス実装ユーティリティ適用の効果 - 3

クライアントクライアント SOAPSOAPサーバサーバ

Webサービス実装Webサービス実装Webサービスクライアント実装Webサービスクライアント実装

同期

同期

//非

同期

共通

非同

期共

通IFIF

同期型API同期型同期型APIAPI

コールバック型APIコールバック型コールバック型APIAPI

ポーリング型APIポーリング型ポーリング型APIAPI

同期型WS同期型同期型WSWS

ポーリング型WSポーリング型ポーリング型WSWS

API層、トランスポート層のアクセス・モデルを完全分離APIAPI層、トランスポート層のアクセス・モデルを完全分離層、トランスポート層のアクセス・モデルを完全分離

Page 28: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

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>

サーバ負荷制御、ポーリング・タイミング制御の実現サーバ負荷制御、ポーリング・タイミング制御の実現サーバ負荷制御、ポーリング・タイミング制御の実現

Page 29: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

29

対策のまとめ

Page 30: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

30

J2EEJ2EE PlatformPlatform

通信部通信部

同期同期APIAPI

クライアントクライアントAPAP

通信部通信部

WebWebサービスサービス

AXISAXISAXISAXIS

クライアントクライアント SOAPSOAPサーバサーバ

非同期Webサービス実装

キャッシュ対応キャッシュ対応

非同期対応非同期対応

非同期対応後のJAX-RPCアーキテクチャ

キャッシュキャッシュ制御部制御部

APIAPI

ローカルキャッシュローカルキャッシュ

キャッシュキャッシュ制御部制御部

APIAPI非同期非同期APIAPI

ワークフローワークフロー制御部制御部

Page 31: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

31

標準化動向

Page 32: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

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>

      ※ 現在、英語版のみの公開です      ※ 日本語版をご希望の方は、メールでご連絡ください

Page 33: 非同期Webサービスの解説と JAX-RPCによる実装例 …people.apache.org/~toshi/docs/JTC2004-N5-jp.pdf3 本日のAgenda • 背景 • 非同期Webサービスの要件

33

ー The End -

Any Questions ?

本資料で利用される、Sun, Sun Microsystems, Java, J2EEなどの語句は、Sun Microsystems 社殿の商標もしくは登録商標です。また、それ以外の製品名等は一般的にそれら各企業の商標ですが、表示を省略しています。