前稿でICEfacesの基本的なアーキテクチャを、そしてこれまでJBoss Seamの基本的な仕組みを見てきた。いよいよ、ICEfacesとJBoss Seamを連携させた場合に、どのような動作をするかについて説明しよう。

ICEfaces×JBoss Seamの動作概要

ICEfacesとJBoss Seamが連携して動作する様子を図5に示す。図5における緑色の箇所が、JBoss Seamを表している。

図5 ICEfacesとJBoss Seamの連携

ICEfacesにおけるリクエストは、クライアント側のAjaxブリッジ(比較的小さなJavaScript)から、サーバ側のAjaxブリッジへと届く。サーバ側のAjaxブリッジの実体は、ICEfaces独自のHTTPサーブレット、擬似サーブレット、サーバから構成される(パーシャルサブミット時のオブジェクトの関係を図6に示す)。サーバ側のAjaxブリッジの最後に、JSFのライフサイクルが実行され、Seamコンポーネントが呼び出される。

図6 サーバ側のAjaxブリッジ(パーシャルサブミット時のオブジェクト)

図7は、パーシャルサブミットのリクエストを受信し、ICEfacesのサーブレットが起動してから、JSFのライフサイクルが実行されるまでの振る舞いを表している。

図7 ICEfacesのサーブレットの処理からJSFライフサイクル実行までのシーケンス

パーシャルサブミットのリクエストを受信すると、まずHTTPサーブレットであるPersistentFacesServletのservice()メソッドが実行される。その中で、図6に示されるように、擬似サーブレット群のservice()メソッド、そしてサーバ群のservice()メソッドが順々に実行される(図7では省略している)。パーシャルサブミットにおいては、Ajaxブリッジでの最後に、ReceiveSendUpdates#service()メソッドが実行され、この中でJSFのライフサイクル(図7ではexecute()メソッドのみを記述)が実行される。JBoss Seamにおいては、前述した通り、このライフサイクルの各フェーズの前後(beforePhase()、afterPhase()メソッド)において、コンポーネント、コンテキストの管理に必要な処理を実行している。

ICEfacesにおいては、通常のサブミットはもちろん、パーシャルサブミットであっても通常のJSFのライフサイクルが実行されるため、上記のようにJBoss Seamと自然に連携することが可能となっている。これにより、ICEfacesを用いて、プレゼンテーション層をリッチかつインタラクティブに構築し、ビジネス層以降をJBoss Seamにより構築することが可能になっている。

ICEfacesにおけるJBoss Seam対応

このように、ICEfacesとJBoss Seamは比較的自然に連携させることが可能なのだが、ICEfacesにおいて、JBoss Seam特有の処理を実行している箇所も存在する。具体的には、SeamUtilities#isSeamEnvironment()メソッドにより、JBoss Seamを用いているかどうかを判定し、処理を分岐している箇所が存在する。動作概要の説明の最後に、JBoss Seam特有の処理について簡単に紹介しておく。

GETリクエストへの対応

ICEfacesにおいては、GETリクエスト(non-facesリクエスト)であっても、すでに訪れたページであれば、既存のコンポーネントツリーをリストアする。しかしJBoss Seamでは、対話を用いることで複数ブラウザによる操作などにも対応している。このため、JBoss Seamを用いている場合には、ICEfacesでは、標準のJSFの仕様通り(JSFのライフサイクルをショートカットして)新しいViewRootを作成する。

対話IDへの対応

JBoss Seamにおいては、対話を識別するために対話ID(Conversation ID)を用いている。ICEfacesのパーシャルサブミットにおいても、この対話IDが必要であるため、リクエスト中から対話IDを取得し、フォームレンダラによりDOMツリーへレンダリングする。

Seamデバッグページへの対応

Seamデバッグページとは、WebブラウザからSeamコンポーネントの内容を確認できる機能である。ICEfacesはリクエストをインターセプトし、デバッグのリクエストである場合には、Seamデバッグページをレンダリングする。