JSFに触ってみる

JSFって?

JSFJavaServer Faces)は、Sun Microsystemsが策定したWebアプリケーションフレームワーク
ユーザインタフェース開発)用の仕様(JSR-127)です。
つまり、実際にWebアプリケーションを開発する場合は、実装が必要になります。
今のところ、SunのRIやMyFacesといった実装が存在します。


特徴

  1. Ease-of-Development

EoD(Ease of Development)は、「開発をより簡単にしよう」というJavaの一つの流れです。
EoDでは、開発生産性を上げるとともに、要求される技術者のスキルを低くし、他言語の技術者が
Javaへ入り込みやすい環境を提供します。
特にJSFでは、「ツール(IDE)を利用することにより開発を簡単にする」という考え方が前提としてあり、
VBVisual Basic)のようなGUIライクな開発スタイルを想定しています。

  1. Standardization

Standardization(標準化)の一番のメリットはフレームワーク導入コストの削減が可能である
ということです。
そもそもフレームワークは開発生産性を向上してくれるものですが、フレームワークの使い方を覚える
為にはそれなりの時間が必要となります。
ところが、プロジェクトにより利用されるフレームワークは様々です。
プロジェクトが変わる度に別のフレームワークの使い方を学習しなければなりません。
そこで、標準化フレームワークであるJSFを利用することで、フレームワークを乗り換えるコストを
削減しようということが狙いです。
JSFは、JCPJava Community Process)というJavaの標準化プロセスを経て作られています。
JCPで作られる仕様はJSR(Java Specification Requests)と呼ばれ、仕様毎に番号で管理されます。
JSFは、JSR127で議論が交わされ、仕様が策定されました。

  1. Device Independence

Device Independence(デバイスの独立)は、クライアント端末の切り替えを容易にします。
つまり、どういうことかというと例えばクライアントをブラウザ(HTML)から携帯端末(WML)へ
容易に移行できるということです。
JSFでは、ビューとロジックが明確に分離して設計されている為、同じビジネスロジックを異なるビュー
でも流用することが可能です。

ライフサイクル

JSFアプリケーションにおいて、「リクエストを処理する一連の流れ」です。
フェーズとは、ライフサイクル中の処理単位のことです。

①Resotre Viewフェーズ:
リクエスト送信元の画面構造(JSFタグの階層)をJavaのオブジェクト(UIコンポーネント)で構築する。
コンポーネントツリーの構築)


②Apply Request Valuesフェーズ:
①で構築したオブジェクト(UIコンポーネント)に、画面の値を設定する。


③Process Validationsフェーズ:
②で設定した値に対し、バリデーション(値の検証)を行なう。(入力チェック)
バリデーションに失敗した場合は、⑥Render Responseに進みます。(④、⑤はスキップ)
バリデーションに成功した場合は、値のコンバージョンを行ないます。(String→Integer等)


④Update Model Valuesフェーズ:
UIコンポーネントの値を、モデルへ反映します。
モデルとは、一般的にビジネスドメインのオブジェクトを指しますが、
JSFでは、managed bean、またはbacking beanと呼びます。


Invoke Applicationフェーズ:
このフェーズでは、アクションの実行が行なわれます。
アクションの結果により、遷移先が決まります。


⑥Render Responseフェーズ:
このフェーズでは、UIコンポーネントから画面が作成されます(レンダリング)。


Managed Bean

managed bean(backing bean)は、JSFで利用するJavaクラスのことです。
このJavaクラスは、faces-config.xmlのmanaged-bean要素に登録して利用します。


JSPからJavaクラスへアクセスするには以下のようにJSPへ記述します。
・プロパティの利用

<h:outputText value="#{mybean.name}


・メソッドの利用

<h:commandButton action="#{mybean.doAction}" value="OK"/>


JSFのEL(Expression Language)表記

アクセス
プロパティ myBean.number
配列 myArray[2]
マップ myMap{"key"]


※.JSTLのEL表記は「${・・・}」ですが、JSFでは「#{・・・}」です。
JSFタグ内では、JSFのELしか記述できない。

ナビゲーション

ナビゲーションとは、画面遷移のことで、ナビゲーションの定義をナビゲーションルールと言います。
また、各画面はそれぞれID(viewID)を持ちます。
ナビゲーションルールは以下の要素で構成されています。

  • 遷移元の画面ID
  • それに対応した遷移先の画面ID
  • その遷移が行なわれる条件


要素 説明
navigation-rule ナビゲーションルール。faces-config上に複数記述することができる。
from-view-id 遷移元のviewID /hello.jsp
navigation-case 遷移先パターンを一つ表します。
from-outcome アクションの結果。アクションとは、JSPのaction属性で指定した文字列。またはアクションメソッドの戻り値です。 success
to-view-id 画面遷移先のviewID /world.jsp
from-action アクションのメソッド。メソッドバインディングを用いて指定します。 #{useBean.add}
redirect リダイレクトを行なうかどうか。この要素を指定すると、フォワードではなくリダイレクトされます。

バリデーション

標準バリデータ

JSFで用意されているバリデータは以下の3つです。

  • DoubleRangeValidator
    • 小数(double型)の精度で範囲チェック
  • LongRangeValidator
    • 整数(long型)の精度で範囲チェック
  • LengthValidator
    • 文字数チェック


使用例

<h:inputText id="first" size="8" required="true" value="#{userBean.firstNumber}">
    <f:validateLongRange minimum="0" maximum="100" />
</h:inputText>
メソッドバリデータの作成

標準バリデータだけで行なえる検証は、上記の3種類に限られます。
標準バリデータで行なえない検証が必要になった場合、独自にバリデータを作成することになります。
その一つがメソッドバリデータです。


メソッドバリデータは、次のようにして作成します。

  • managed beanにバリデートメソッドを作成します。
  • 入力タグのvalidator属性へそのメソッドを指定


バリデートメソッドの例

public void check(FacesContext context, UIComponent, Object value) {
   ValueHolder from = (ValueHolder)component.findComponent("first");
   Integer fromValue = (Integer)from.getValue();
   if(fromValue.intValue() >= ((Integer)value).intValue()) {
      FacesMessage errerMsg = new FacesMessage("項目1は項目2より小さい値でなければなりません。");

        throw new ValidatorException(errerMsg);
   }
}


JSPの例

<h:inputText id="first" size="8" required="true" value="#{userBean.firstNumber}">
    <f:validateLongRange minimum="0" maximum="100" />
</h:inputText>

<h:inputText id="first" size="8" required="true" 
             value="#{userBean.secondNumber}" 
             validator="#{userValidator.check}" />

メッセージと国際化

メッセージリソースの指定


アプリケーションで利用するメッセージはソース中に文字を埋め込まずに、
外部のリソースファイルに定義します。
メッセージリソースファイルは、faces-config.xmlのapplication要素で指定します。

<application>
    <message-bundle>myapp.Messages</message-bundle>
    <locale-config>
        <default-locale>en</default-locale>
        <supported-locale>en</supported-locale>
        <supported-locale>ja</supported-locale>
    </locale-config>
</application>


この例では、リソースファイル(message-bundle)にmyapp.Messageを指定しています。
このリソースファイルは、クラスパス上でmyapp/Messages.propertiesという名前で配置します。
(日本語リソースの場合はmyapp/Messages_ja.properties)


このように複数のロケールを予め定義しておくことで、クライアントのブラウザのロケール設定により
表示されるメッセージを切り替えることができる。