JSF 1.0が2004年3月3日に正式リリースされました(http://java.sun.com/j2ee/javaserverfaces/)。
紙面ではJSF 1.0 Early Access 4(EA4)を扱っています。印刷所入稿ギリギリのタイミングで1.0が正式リリースされたため、紙面での対応は間に合いませんでした。
バージョン1.0正式版の仕様はEA4とは大きく異なっており、記事で扱った内容では正式版を扱うことができません。そこで、記事で扱ったサンプルアプリケーションを中心に変更点をここにまとめます。
なお、本書ダウンロードコーナーには、変更後のサンプルアプリケーションも公開していますので、参考にしてください。
EA4のサンプルはTomcat 5系でしか動かないように実装されていましたが、正式版のサンプルではこれが修正されて、Tomcat 4系でも動作するようになっています。EA4のチュートリアルではServlet 2.3/JSP 1.2以上をサポートすることが明記されていましたが、動作にはTomcat 5系が必要でした。
次のクラスは必要なくなります。
これまでActionやActionListenerの派生クラスとして実装していたビジネスロジックはJavaBeansに移動します。ActionListenerに関してはこれまでと似た使い方ができますが、P.65の図2の処理の過程から選択することはできなくなります。
ActionとActionListeneの派生クラスとして実装していたビジネスロジックは次のようにInquiryBeanクラスに移動することができます。
...(省略) public class InquiryBean implements Serializable { // (1) InputActionListenerクラスの実装を移動 public void inputEvent(ActionEvent ev) { } // (2) InputActionクラスの実装を移動 public String input() { return "success"; } // (3) ConfirmActionクラスの実装を移動 public String confirm() { return "success"; } ...(以下省略)
ActionListenerの派生クラス(InputActionListener)では、ActionListenerインタフェースをimplementsに記述することになり、これに従ってこのインタフェースに定義されているメソッドをオーバライドする必要がありました。
正式版ではActionListenerインタフェースをimplementsに記述する必要はなく、任意のメソッド名にすることができます。ただし、上記ソースの(1)のように引数を1つ用意し、この引数をActionEventクラスにする必要があります。
変更には規則性があります。たとえば以下のように“_”の後の英字を大文字にして、“_”を消して繋げます。
すべてのタグがこの規則に則って変更されるわけではありません。詳しくは仕様を確認してください。
本サンプルでは単純に<f:use_faces>を<f:view>に変更するだけで動作します。
日付専用のカスタムタグがなくなります。以下のようにして、入れ子に日付の型であることを指定します。
<h:output_datetime valueRef="InquiryBean.replyDay" formatPattern="yyyy/MM/dd"/>
<h:outputText value="..."> <f:convertDateTime pattern="yyyy/MM/dd"/> </h:outputText>
EA4ではJSTLを使用してリソースを読み込んでいましたが、正式版ではJSFのカスタムタグを使用します。
<fmt:setBundle basename="com.wdpress.jsf.inquiry.Resources" scope="session" var="inquiryBundle"/>
<f:loadBundle basename="com.wdpress.jsf.inquiry.Resources" var="inquiryBundle"/>
EA4ではリースバンドルを特定する名前とそのリソース内の文字を特定する名前の2つの属性を指定する必要がありましたが、正式版ではELを使用して1つの属性でリソースを特定します。ELの表記はやや特殊です(5で説明)。
<h:output_text key="inputName" bundle="inquiryBundle"/>:
<h:outputText value="#{inquiryBundle.inputName}"/>:
通常、ELは“${...}”というように“$”で始まる表記をしますが、正式版では“#”を使用します。この変更の詳細はJSFの仕様書を参照してください。
<h:outputText value="#{inquiryBundle.inputName}"/>:
また、属性valueRefにELを記述することが多いですが、全般的にこの名前はvalueに変わる傾向があります。
入力必須をチェックさせる方法は、タグの入れ子ではなく属性で指定するようになります。入力系全般にいえます。
<h:input_text id="name" valueRef="InquiryBean.name"> <f:validate_required/> </h:input_text>
<h:inputText id="name" value="#{inquiryBean.name}" required="true"/>
入力必須などのチェック結果のエラーメッセージを表示するタグが変わります。色が指定できない代わりにスタイルシートの指定ができるので、これを使用して色を設定することになるでしょう。
<h:output_errors for="name" color="red"/>
<h:message for="name"/>
送信ボタンは、まずリソースの読み方がELの記述になります。次に、ActionやActionListnerの派生クラスへのへマッピング方法がELを使用して直接JavaBeansのメソッド名を記述します。
<h:command_button type="submit" key="confirmButton" bundle="inquiryBundle" commandName="input" actionRef="InquiryBean.input"> <f:action_listener type="com.wdpress.jsf.inquiry.InputActionListener"/> </h:command_button>
<h:commandButton type="submit" value="#{inquiryBundle.confirmButton}" action="#{inquiryBean.input}" actionListener="#{inquiryBean.inputEvent}"/>
たとえば、このボタンのActionはInquiryBeanクラスのinput()メソッドに通知されます。
EA4のサンプルでは入力必須チェックのエラーメッセージが英語で表示されましたが、これをカスタマイズできるようになります(EA4でもできたかもしれませんが、わかりづらいものでした)。
たとえば以下の場所にメッセージリソースを置くことを考えます。
com\wdpress\jsf\inquiry\Messages.properties
faces-config.xmlに次の設定を追加します。
...(省略) <faces-config> <!-- メッセージリソースの設定 --> <application> <message-bundle>com.wdpress.jsf.inquiry.Messages</message-bundle> <locale-config> <default-locale>ja</default-locale> </locale-config> </application> ...(省略)
たとえば、入力必須チェックのエラーメッセージをカスタマイズする場合は次のような内容になります(native2asciiによるエスケープは必要です)。
javax.faces.component.UIInput.REQUIRED=必須です。
URLマッピングがStrutsのように拡張子で指定するようになります。厳密な規約はないですが、このようにしておくのが一般的となるでしょう。URLのファイル名部が“.faces”で終われば、JSFで処理されることになります。
<!-- Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping>
<!-- Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.faces</url-pattern> </servlet-mapping>
faces-config.xmlのタグが変わりました。特にサンプルでは次の部分が変わります。
<navigation-rule> <from-tree-id>/input.jsp</from-tree-id> <navigation-case> <from-outcome>success</from-outcome> <to-tree-id>/confirm.jsp</to-tree-id> </navigation-case> <navigation-case> <from-outcome>failure</from-outcome> <to-tree-id>/input.jsp</to-tree-id> </navigation-case> </navigation-rule> <navigation-rule> <from-tree-id>/confirm.jsp</from-tree-id> <navigation-case> <from-outcome>success</from-outcome> <to-tree-id>/thanks.jsp</to-tree-id> </navigation-case> <navigation-case> <from-outcome>failure</from-outcome> <to-tree-id>/input.jsp</to-tree-id> </navigation-case> </navigation-rule>
<navigation-rule> <from-view-id>/input.jsp</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/confirm.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>failure</from-outcome> <to-view-id>/input.jsp</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/confirm.jsp</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/thanks.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>failure</from-outcome> <to-view-id>/input.jsp</to-view-id> </navigation-case> </navigation-rule>