2007-05-08 15:41:23

JSON-RPCでのサービス公開

テーマ:JSON-RPC

Author: BigBird


Aixs2等を使用して、Javaのメソッド群をWebサービスとして公開するという手もあるが、Ajaxと簡単にフィットするJSON-RPCを使用する程度でよい場合もあるでしょう。

JSONとはJavaScriptObjectNationのことで、JavaScriptno言語使用のサブセットであるデータ交換フォーマット仕様です。詳細はJSONオフィシャルサイト(http://www.json.org )を参照ください。

本文書では、JSON-RPCでJavaメソッドを公開する方法をサンプルプログラムを例に記載します。なお、本例ではSpring、JSFとJSON-RPC-Javaの組み合わせで行います。

サンプルプログラムの作成はExadelStudioを使用していますが、ExadelStudioを使用していない場合でも特に問題はありません。

1.サンプルプログラムの構成

本例では従業員検索サービスを作成し、これをJSON-RPC-Javaを使用してサービスを公開します。
今回作成するソースは以下のとおりです。
(サンプルソースを公開したいのですが、適当な格納場所ないし方法が分からない、ということで今しばらくお待ちください。)

(1)従業員検索サービスクラス
 sample.services.EmployeeList
(2)従業員クラス
sample.domain.Employee
(3)ログインハンドラクラス
sample.backingbean.LoginHandler
(4)クライアントアプリケーションファイル
WebContent/contents/search_service/SearchEmployee.jsp
(5)ログインファイル
WebContent/contents/Common/Login.jsp
(6)部門選択セレクトボックスのオプションデータ用ファイル
WebContent/contents/search_service/selectDeptData.jsp

開発リソース
図.開発リソース(TestClass.javaは必要ありません)

従業員検索サービスは、ユーザが指定した検索条件に合致する従業員のリストを返却します。
以下に画面イメージを掲載します。

部門検索画面

セレクトボックスで部門を選択し、検索ボタンをクリックすると、画面上にその部門に所属する従業員の人数と、従業員オブジェクトを表示します。

さて、JSON-RPC-Javaは、”特定のユーザにのみサービスを公開する”ことを実現させるため、HTTPSession特性を考慮したインプリメントになっています。

よって、今回はJSFバッキングビーンのログインハンドラを作成し、ログインに成功したユーザのみが従業員検索サービスを使用できる、という処理にします。

これを踏まえた画面遷移は以下のようになります。

ログイン画面  
ログイン画面
    ↓
(ログイン処理)
    ↓
部門検索画面
検索画面

クライアントアプリケーションである検索画面の構築には、JSON-RPC-Javaが提供するJSON-RPC用のJSON-RPC JavaScript client(jsonrpc.js)と、AjaxのprototypeおよびDojoライブラリを使用します。
サーバ側のサービスには、jsonrpc.jsを使用して接続します。

なお、今回はjspでクライアントを作成しましたが、HTMLで作成しても問題ないです。


2.必要ソフトウェアの準備
今回のサンプルを構築する上で必要となるソフトウェアは以下のとおりです。

■JSON-RPC-Java(本稿執筆時の最新版はjson-rpc-java-1.0.zip
■Dojo
■Prototype

なお、今回はExadelStudio4.0.4を使用して(Eclipse3.2.0)、JSFプロジェクトとしてサンプルを作成しました。
JSFはApacheMyFaces1.1.4を使用しています。必ずしも同じバージョン環境である必要はありません。適宜用意してください。


3.環境の準備

(1)サンプルEclipseプロジェクトの作成
Eclipseでサンプルプロジェクトを作成します。今回はJSFプロジェクトを作成します。

(2)JSON-RPC-Javaのインストール
ダウンロードしたファイルを解凍します。解凍したフォルダの中に「jsonrpc-1.0.jar」があります。このjarを作成したEclipseプロジェクトのWebアプリケーションライブラリー(WebContents/WEB-INF/lib)にコピーします。

(3)JSONRPCServletのweb.xmlへの登録
JSON-RPCクライアントからのコールを受け付ける、JSONRPCServletをプロジェクトのweb.xmlに登録します。
web.xmlの編集


(4)JSONRPCBridgeの生成
JSONRPCBridgeは、公開するサービスのインスタンスに対する参照を保持し、そのインスタンスに対してメソッド呼び出しを行います。
JSONRPCBridgeインスタンスオブジェクトはHTTPSessionオブジェクトに「JSONRPCBridge」という属性名で登録する必要があります。この属性名によりJSONRPCServletはブリッジすべき場所を特定することが可能となります。
JSONRPCBridgeはセッション特性をもつようインプリメントされていますが、これはサービスインスタンスを特定のユーザにのみ公開することによりアプリケーションのセキュリティを改善するための理由からです。
このような考えのもと、特定のサービスインスタンスをユーザに提供することができ、とりわけアプリケーション認証機構をパスしたユーザにのみ提供する、ということが可能になります。

本稿においてはJSONRPCBrigeの生成をJSFに依頼します。
HTTPSessionオブジェクトとして生成するために、プロジェクトのfaces-config.xmlに以下の記述を追加します。

faces-config.xmlの編集


4.実装

(1)従業員検索サービスクラスと従業員クラス

EmployeeList.java(パッケージsample.services)
Employee.java(パッケージsample.domain)

いたってシンプルです。以下にUMLを掲載します。
クラス図

Employeeクラスはid,name,deptCd(部門コード)を属性とするシンプルなクラスです。
EmployeeList#findByDept()はEmployeeインスタンス配列を返却するように適宜実装してください。
バッキングビーンであるログインハンドラLoginHandlerは、属性としてEmployeeListインスタンスを保持させます。
インスタンスの注入はコンストラクタにて行います。これも適宜実装してください。

(2)JSF上の設定(faces-config.xml)
faces-config.xmlを編集し、ログインハンドラインスタンスおよびJSONRPCBridgeインスタンスをJSFに生成させます。
いずれのインスタンスもsessionスコープで生成させます。

managed-bean

図. faces-config.xmlにおけるmanaged-beanでのインスタンス生成

(3)JSONRPCBridgeへのサービス登録
ログイン処理(あくまでもダミーですが)をしたのち、以下の手順をコーディングします。

(3-1)JSFサービスコンテキスト取得
(3-2)セッションの取得
(3-3)JSONBridgeインスタンスの取得
(3-4)サービス公開したいインスタンス(employeeService)のJSONBridgeへの登録

ログイン処理(login_action())のコーディングイメージを掲載します。

ログインアクション2


サービスの登録単位はインスタンス単位になります。当然そのインスタンス(のクラス)がpublicで公開しているメソッドは全て公開されます。

(4)クライアントの実装
DojoやPrototypeの説明は割愛し(別の記事で解説します)、JSON-RPCClient部分に関して説明します。

(4-1)JSON-RPC Clientの初期化
Clientインスタンスを作成します。作成する際、JSON-RPCサーブレットの場所を指定します。今回は同一サイト内にクライアントおよびサーバを配置しました。

jsonrpc = new JSONRpcClient("/JSONRPCSamp/JSON-RPC");

(4-2)メソッドのコール
JSON-RPC Clientインスタンスを使用してコールします。コールする形式は以下のとおりです。

[JSON-RPCインスタンス名].[コールしたいサービスのインスタンスのセッション属性名].[コールしたいメソッド名]

今回は、JSON-Bridgeに登録したインスタンスのセッション属性名が”employeeService”、コールしたいメソッドは”findByDept()”ですので、コールする際は以下のコードとなります。

deptは部門コードです。セレクトボックスで選択したものを引数として使用するよう、適宜実装を行ってください。

var employees = jsonrpc.employeeService.findByDept(dept);

正常に実行できた場合、指定した部門コードに基づき、employeesにはEmployeeインスタンスが複数格納されているはずです。
単純に件数分だけループ処理をし、Employeeインスタンスにアクセスすることが可能です。

for(i=0; i<employees.length; i++) {
employee = employees[i];
employeeString = employeeString + "[" + employee.id + ":" + employee.name + ":" + employee.deptCd + "]";
}

さて、AXISのTCPMonitorでキャプチャした、サーバからのレスポンス(結果データのみ)は以下のようになっていました。

{"result":[
{"javaClass":"sample.domain.Employee","deptCd":"Sales","name":"yamada","id":"001"},
{"javaClass":"sample.domain.Employee","deptCd":"Sales","name":"tanaka","id":"003"},
{"javaClass":"sample.domain.Employee","deptCd":"Sales","name":"suzuki","id":"006"},
{"javaClass":"sample.domain.Employee","deptCd":"Sales","name":"yamashita","id":"008"},
{"javaClass":"sample.domain.Employee","deptCd":"Sales","name":"sugiyama","id":"010"}
],
"id":6}

このようにJSON形式でデータを取得すれば、JavaScript側での値の受け取りと取扱が非常に簡単になります。



以上


Amebaおすすめキーワード