BT

Java EE 6 Web 層: JSF 2 が手に入れた Facelet,複合コンポーネント,Partial State Saving,そして Ajax

| 作者: Charles Humble , 翻訳者 吉田 英人 投稿日 2010年2月16日. 推定読書時間: 1 分 |

原文(投稿日:2010/01/28)へのリンク

前回の記事で私たちは,Servlet 3.0 API とその Ajax サポートについて取り上げた。Servlet API を Java EE Web フレームワークの技術ファミリに相応しいものにするためには,非常に多くの作業が必要であったが,JavaServer Faces (JSF) はフレームワークのレベルでステートフルな UI コンポーネントツリーを維持していることもあり,Ajax のアプローチにも無理なく対応可能なはずだ。それでも JSF 1.x では組み込みでの Ajax サポートは実現されず,Ajax4jsf/RichFaces,ICEFaces,ADF Faces/Trinidad といったサードパーティのライブラリにその機能を依存していた。今回 EE6 で提供される JSF 2.0 では,パーシャル・ページ・アップデート (partial page update)とパーシャル・ビュー・トラバーサル(partial view traversal) のサポートを追加し,ビュー内の選択されたコンポーネントをページ全体の再描画なしに処理,表示可能とすることで,この機能に対応する。ユーザインターフェースでイベントが発生すると,サーバがツリー上の関連するセクションの処理のみを実行して,その結果発生した変更をブラウザにプッシュして返す,という仕組みだ。
JSF 2 の Ajax サポートではさらに "ビヘイビア(behaviour)" という新たな概念も導入されている。コンポーネントは,ある機能をそのコンポーネントにとって最良の方法でサポートするための手段として,ビヘイビアをアタッチして所持することができる。例えばテキストフィールドには,そのフィールドの onChange( ) JavaScript イベントに結合されたイベントを発生させるためのビヘイビア AjaxBehaviour がアタッチされる。コマンドボタンにも同様に,そのボタンの onClick( ) イベントからトリガされる AjaxBehaviour がアタッチされる,という具合だ。

JSF 2 エキスパートグループにとって Ajax サポートは ,コミュニティの経験を活用できた多くの領域のうちのひとつであると同時に,JSF 1 に対して繰り返されてきたもうひとつの批判,エキスパートグループへの限られた外部入力によってデザインされている,という指摘への対応でもある。例えば,JSF 2 ではビューレイヤとしての JSP が廃止され,より JSF 的な Facelet に置き換えられている。Facelet は元々 Apache ライセンスのオープンソースプロジェクトとして生まれ,JCP とは離れた場所で開発が続けられてきたものだ。Facelet は Hans Bergsten 氏の記事 "JSP 廃止による JSF 改良 (Improving JSF by Dumping JSP)" で提起された,JSF と JSP の表示順の違いなどの諸問題に対する解決策として,JSF 開発者の間では広く使用されてきた。
Facelet は標準化され,スタンドアローンであった頃よりも深くフレームワークに結合されたため,エキスパートグループがその主要なアイデアをさらに発展させることも可能になった。例えば,Facelet は複合コンポーネントによるテンプレート処理をサポートするが,複合コンポーネントには任意の有効な Facelet XHTML ページを用いることができる。しかし JSF 1.x での Facelet では,複合コンポーネントは真の UI コンポーネントとしては扱われていなかった。しかし JSF 2 においては複合コンポーネントは本当の UI コンポーネントであるので,バリデータ,コンバータ,リスナ(アクションと値変更のどちらも)をサポートすることができる。

エキスパートグループはまた,Seam フレームワーク からアイデアを大々的に採用した。その中のひとつ,Seam のページパラメータ (page parameter) を発展させたビューパラメータ(view parameter) は,クエリ文字列パラメータとモデル値のマッピングである。マッピングの指定は,ビューの <f:metadata> セクションに新たに追加された <f:viewParam> コンポーネントを使用して行う。ビューパラメータは GET リクエストのパラメータを JSF ライフサイクルに追加して,パラメータのデコード,タイプ変換,バリデーション,モデル更新などを完全にサポートする。
さらに GET リクエストは,アプリケーション定義のリスナを PreRenderViewEvent によって起動することができる。PreRenderViewEvent はビューパラメータの処理が完了した後,ビューが表示される前に発行されるイベントだ。

GET リクエストサポートの最後となるのは,標準HTML RenderKit に追加された,関連性のある2つの機能 (<h:link> と <h:button>) だ。GET リクエストリンクの生成手段を提供するものであり,ビューパラメータとの組み合わせによって JSF 2 のブックマーク可能なページの基礎となる。

前述の PreRenderViewEvent は システムイベント (System Event) の1例である。Seam フレームワークに影響されたもうひとつの JSF 新機能であるシステムイベントは,Ken Paulsen 氏による JSFTemplating からの影響も受けている。システムイベントは JSF ライフサイクル中に発生する事象に対する publish/subscribe 方式のイベントバスであり,以下の3つのスコープでリスナを登録することができる。

  • コンポーネント - UIComponent.subscribeToEvent()
  • ビュー - UIViewRoot.subscribeToEvent()
  • アプリケーション - Application.subscribeToEvent()

発行(publish)については Application.publishEvent() を共通で使用する。

JSF 2 はその他のフレームワーク利用者の不満点に対しても,以下のように数多く対応している。

  1. ナビゲーションの改良: 新たに暗黙的ナビゲーションルールが導入されたことにより,すべてのケースを faces-config.xml に定義する必要がなくなった。また,<if> コンフィギュレーション要素を使用した EL 式で指定する条件付きのナビゲーションがナビゲーションサブシステムでサポートされるようになった。
  2. 状態保存: JSF の状態情報はサイズがかなり大きく,クライアント側でのセッション情報の保存が現実的ではないため,結果的にセッションの使用負荷が高くなっている。JSF 2 では Apache Trinidad にあった State Saving という状態保存機能を採用し,これを Facelet で記述されたページの既定値とした。パーシャル・ステート・セービング (Partial State Saving) と呼ばれるこの新しい実装では,コンポーネントツリーが利用されている。ビューの再実行によってコンポーネントツリーを初期化した後に,それ以降に実施された変更内容を反映して更新する,という仕組みである。この方法は,マークアップベースの UI では状態情報の多くがページ内に組み込まれている,という事実を利用するもので,その結果 pre-view 状態のサイズが JSF 1.2 との比較で約4分の1に減少する,という大きな効果を上げている。
  3. 単一ページでの複数コンポーネントライブラリ使用: JSF 1.x はリソースサービスをサポートしていなかったため,ほとんどのコンポーネントライブラリは,その目的のサーブレットあるいはフィルタを独自に開発していた。Shale Remoting (現在は使われていない),weblets などがその実例だ。この種のリソースサーブレットが頻繁にクラッシュするため,アプリケーションの1ページ内で複数のコンポーネントライブラリを使用する開発は非常に難しいものだった。JSF 2 はクラスパスあるいはファイルシステムを参照してリソースへのアクセスを定義する標準的な機構を提供して,イメージ,JavaScript,CSS ファイルなどをビルトインサポートすることでこの問題を解決している。
  4. コンフィギュレーションでのアノテーションサポート: マネージドビーンとカスタムコンポーネントの両方に対して新たにアノテーションサポートが追加され,作成の必要な XML 定義の量が削減された。

最後に,JSF 2 で導入された小さな拡張の数々から,重要なものを紹介する。

  1. "プロジェクトステージ (project stage)" パラメータの標準化: プロジェクトステージは,予め定義された選択項目のセットによって JSF の振る舞いを操作する手段を提供するものだ。選択項目の指定にはコンテキストパラメータ,あるいは JNDI を使用する。例えば,開発中はブラウザに追加的なデバッグ情報を表示し,製品時にはそれを抑制する,といったコントロールを行うには,製品(production),開発(development),ユニットテスト,システムテストなどをステージとして定義しておいて,その既定値を製品にしておけばよい。ランタイムでは,アプリケーションオブジェクトに対して Application.getProjectStage( ) をコールすることによってコンフィギュレーション設定値を取得することができる。
  2. 新しいスコープ: ユーザが現在のビューでの操作を完了するまで状態を保存するビュースコープや,Ruby on Rails からアイデアを拝借したフラッシュスコープなどがある。フラッシュスコープに配置されたものは,同じユーザが参照する次のビューすべてに公開され,その後消去される。
  3. Bean Validation の組み込み実装: JSR 303/Bean Validation は,ORM ツールを通じた DDL 更新や Java Persistent API による挿入/更新時のエンティティ検証,JavaServer Face コンポーネントなどのような,アプリケーションの異なる層間を越える制約を表現するための統合化された機構を提供するものだ。Java EE スタックの他の部分と同様,JSF 2 も Bean Validation 制約に従って動作するように変更された。
  4. エラー処理の改良: Facelet エラーページの情報量が JSF 1.0 よりも豊富になり,Facelet ファイルの行番号などが含まれるようになった。また JSF 2 では新しい ExceptionHandler API も導入され,例外処理に関する集中的な機構が提供されている。

2004年3月に登場して以来,JavaServer Faces は標準的な Java の Web フレームワークとしての批判を数多く受けてきた。JSF 2 では多数寄せられた不満に対応して,数多くの新機能が追加されている。次期 Web アプリケーションに対してコンポーネントベースのアプローチを検討しているならば,再確認する価値がある。ただし JSF 2 の効果を完全に評価するためには,Java EE Web プロファイルのより広いコンテキストにおいて,それを検討する必要があるかもしれない - 特に こちら で説明しているような,タイプセーフとアノテーション駆動の依存性注入フレームワーク,スコープ管理の宣言的方法,コンテキストに結びつけられたコンポーネントの状態とライフサイクル,そして今後の記事で取り上げる予定の EJB/JPA などを提供する CDI (Context and Dependency Injection)などでそれが重要だろう。

この記事に星をつける

おすすめ度
スタイル

こんにちは

コメントするには InfoQアカウントの登録 または が必要です。InfoQ に登録するとさまざまなことができます。

アカウント登録をしてInfoQをお楽しみください。

あなたの意見をお聞かせください。

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする
コミュニティコメント

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

ディスカッション
BT