DATE : 2007/01/30 (Tue)
入力値と Backing Bean 間、Backing Bean と UIInput/ UIOutput 間で値の変換を行う Converter の中でも自作のものを指定する方法には、次の3種類があります。
- UIInput / UIOutput 系の要素の converter 属性で指定する。
- javax.faces.converter.Converter インタフェースを実装したクラスの完全修飾名で指定する。
- アプリケーションに登録された Converter の ID で指定する。
- f:converter 要素で指定する。
それぞれの例を示すと、次のようになります。(「...」は省略を表します)
<%-- converter 属性にクラスの完全修飾名で指定 --%> <h:inputText converter="myapp.MyConverter" ... /> <%-- converter 属性に ID で指定 --%> <h:inputText converter="converter" ... /> <%-- f:converter 要素で指定 --%> <h:inputText ... > <f:converter converterId="converter" /> </h:inputText>
ところで、JSF では、Backing Bean やそのプロパティを指定するためによく次のようなコードを書きます。
<%-- person という Backing Bean の name プロパティを出力する --%> <h:outputText value="#{person.name}" />
(;^ω^)そのため、Converter を指定する際に次の間違いを犯してしまいました。
<%-- 以下は間違い --%> <h:inputText converter="#{converter}" ... />
(;´Д`)間違えて上のように指定した場合、入力値と Backing Bean 間でデータ型が異なっていればアプリケーションがエラーを吐きますが、データ型が同じ(java.lang.String)の場合は、何事もなかったかのように処理が進行します。
参考文献
DATE : 2006/12/25 (Mon)
Java SE 5 以前
ICU4J (International Components for Unicode for Java) ライブラリを使います。ICU は Unicode を処理するライブラリです。Unicode には異なるコードで表された同じ文字を特定のコードに統一する「Unicode 正規化」という仕様があります。ICU は、この仕様に基づいて文字コードを変換します。
Unicode 正規化を用いて全角英数や半角カナを変換するには、com.ibm.icu.text.Normalizer を使用します。target 変数に格納された String 型の文字列を変換するコードは、次のようになります。
String result = Normalizer.normalize(target, Normalizer.NFKC);
「Normalizer.NFKC」というのは、正規化の方法を表しています。「NF」は「正規化形式(Normalizer Form)」を表し、「KC」は「互換合成(Compatibility Composition)」を表しています。つまり、正規化の統一先の文字と互換性のある文字であれば正規化され、1文字分のコードが2つ以上に分かれている場合はコード1つになるように合成されます。そのため、全角英数は半角に、半角カナが全角に変換されるわけです。
Java SE 6 以降
java.text.Normalizer を使います。
上の例を java.text.Normalizer で書き直すと、次のようになります。
String result = Normalizer.normalize(target, Normalizer.Form.NFKC);
参考文献
DATE : 2006/12/24 (Sun)
例えば、次のような入力必須のフォームがあったとします。
<h:form> <h:inputText required="true" /> <h:commandButton value="戻る" action="prev" /> <h:commandButton value="次へ" action="next" /> </h:form>
「戻る」ボタンを押したときには前のページに戻ります。しかし、上のコードではテキストフィールドに何か入力されていないと戻ることができません。
このような入力必須のフォームから入力なしに抜ける方法には、以下の方法があります。
- 「戻る」ボタンを別のフォームにする。
- 「戻る」ボタンの h:commandButton の immediate 属性を true にする。
「戻る」ボタンを別のフォームにする
「戻る」ボタンを別のフォームにします。このようにすると、「戻る」ボタンのあるフォームは入力が必須のフォームではないので、前のページに戻ることができます。
ただし、ページのレイアウトによっては「戻る」ボタンの位置をスタイルシートで調節する必要が出てきます。
「戻る」ボタンの h:commandButton の immediate 属性を true にする
次のように、「戻る」ボタンの immediate 属性を true に設定します。
<h:commandButton value="戻る" immediate="true" action="prev" />
初めに示したコードでは、「The Life Cycle of a JavaServer Faces Page」の図で示されている段階を全て経た上で次の(もしくは前の)ページへ遷移します。この中には「検証処理(Process Validations)」という段階があり、ここで入力がされているかどうかのチェック行われます。
しかし h:commandButton に immediate 属性を付けると、「検証処理」の前にページを遷移させることができます(正確には action 属性で指定したアクションを実行することになります)。具体的には「リクエストの適用(Apply Request)」段階でアクションを処理できます。
図を見ると、「リクエストの適用」の次にある「イベント処理(Process Events)」から最後の「レスポンスの構築(Render Response)」段階に矢印が延びていることがわかります。
参考文献
DATE : 2006/12/12 (Tue)
ユーザの入力値を検証する Validator には以下の2種類があります。
- Backing Bean の、規定の引数を受け付けるメソッド
- javax.faces.validator.Validator インタフェースを実装したクラス
実装した Validator を JSP 内で使用する方法も2種類あります。
- UIInput 系の要素の validator 属性で指定する
- UIInput 系の要素内に Validator を指定した f:validator 要素を含ませる
どの方法で Validator を指定するかは、Validator の種類によって決まります。具体的には、以下のようになります。
Validator の種類 | 指定方法 |
---|---|
メソッド形式 | validator 属性 |
クラス形式 | f:validator 要素 |
例をコードで示すと、次のようになります。ここで、backingBean.validate は backingBean という名前の Backing Bean 内にある validate メソッドを、validator は Validator インタフェースを実装した Validator の ID を表します。また、h:inputText 要素はテキストフィールドを表します。(例に関係のない部分は省略しています)
<%-- メソッド形式の Validator --%> <h:inputText validator="#{backingBean.validate}" /> <%-- クラス形式の Validator --%> <h:inputText> <f:validator validatorId="validator" /> </h:inputText>
これらを互い違いに指定した場合、入力値の検証部分でエラーが発生します。
(;^ω^)一見するとどちらを指定しても良さそうに見えるので、注意が必要ですね。
参考文献
DATE : 2006/12/09 (Sat)
JSF には、ビュー(HTML のフォームなど)と モデルデータオブジェクト間で値を変換するために Converter を使用します。
例えば、javax.faces.convert .DateTimeConverterを使用すると、ユーザがビューに入力した文字列や選択した項目を java.util.Date オブジェクトに変換できます。また、逆にモデルデータオブジェクトの Date オブジェクトを持つプロパティから、ビューに表示する文字列に変換することもできます。
Converter は、javax.faces.convert.Converter を実装することで自作できます。本記事では、Converter を実装する際のポイントをメモしておきます。
Converter の行う変換は、ビューからモデルデータオブジェクトへ行うもの、モデルデータオブジェクトからビューへの変換を行うものの2種類があります。
変換 | 変換を行うメソッド |
---|---|
ビュー → モデルデータオブジェクト | getAsObject |
モデルデータオブジェクト → ビュー | getAsString |
Converter を実装する際には、引数なしのコンストラクタを用意する必要があります。
なお、必ずしも上の2つのメソッド全てをしっかり実装する必要はありません。行う変換が1種類のみであれば、片方は簡単な実装で済ませても構いません。
ただし、変換対象のオブジェクトとして、null が渡されることがあるので注意が必要です。例えば、モデルデータオブジェクトからビューへの変換では特に処理を行わない場合(例えば、モデルデータオブジェクトのプロパティが String などで変換の必要がない場合)、次のようなコードを書いてしまうことがあります。
public String getAsString( FacesContext context, UIComponent component, Object value) { if (context == null || component == null) { throw new NullPointerException(); } return object.toString(); }
しかし、変換対象のモデルデータオブジェクトのプロパティが null だった場合、引数 value も null となるため NullPointerException が発生します。
value が null の場合、Converter#getAsString(FacesContext, UIComponent, Object) の仕様では長さ0の文字列を返すという仕様になっています。
そのため、特に処理を行わないメソッドは、次のように書く必要があります。
public String getAsString( FacesContext context, UIComponent component, Object value) { if (context == null || component == null) { throw new NullPointerException(); } if (value == null) { return ""; } return value.toString(); }