検証機能を拡張する
標準の検証機能では十分でない場合、その検証ロジックを実装できるようにもなっています。その方法は2種類用意されており、ManagedBeanに対してメソッドを追加して記述する方法と、検証用クラスを設けて利用する方法があります。どちらの方法についても一定の規則に従って実装するだけで、記述するロジックは同じものになります。
ではこの2つの方法について、サンプルコードを交えて解説していきます。
ManagedBeanに検証用メソッドを追加する方法
1つ目はManagedBeanに検証用のメソッドを追加して、検証機能を搭載させる方法になります。まずはManagedBean側の実装方法を見てみましょう。
@Named(value="user") … (1)
@RequestScoped
public class SampleJSFBean implements Serializable {
…(中略)…
public void validaitonUsername(FacesContext fc, UIComponent uic, Object value) { …(2)
String input = (String)value;
if ( input == null || input.equals("") ) {
throw new ValidatorException(new FacesMessage("名前は必須入力です")); …(3)
}
if ( input.length() >= 16 ) {
throw new ValidatorException(new FacesMessage("名前は15文字以内です")); …(4)
}
}
}
このリスト4は、前回紹介しましたManagedBeanに対してユーザ名の検証機能メソッドを追加したものです。ではリスト中に番号をつけた箇所について説明します。
(1)の@Named(value="user")を付けることで、JavaEEコンテナはこのManagedBeanをuserの名称で管理します。これによりFaceletsからもこの名称で参照でき、メソッドの呼び出しも行えます。
(2)は 検証メソッドです。引数は必ず(FacesContext fc, UIComponent uic, Object value)になります。
第1引数にて指定されたFacesContextはJSFアプリケーションの現在の状態を保持しているオブジェクトです。従来のサーブレットのようにリクエスト属性やセッション属性の内容を取得するためのgetExternalContext()や、検証結果のメッセージを追加するaddMessage()などのメソッドを利用できます。
第2引数にて指定されたUIConponentは、この検証メソッドを利用しているコンポーネントのオブジェクトです。uic.getClientId()でFaceletsで定義したコンポーネントのidを取得できるメソッドなどが利用できます。最後の引数valueからは、そのコンポーネントから入力された値が入っています。クラスがObjectのため、検証機能を実装する際には適したクラスにキャストしてから利用することになります。このリスト4ではStringにキャストし、入力値の検証を(3)、(4)で行っています。
(3)、(4)は、検証機能を実装している箇所になります。検証エラーを出す際にはValidatorExceptionをスローすることで処理が中断し、検証エラーとできます。またメッセージをここでも定義でき、FacesMessageを作成してValidatorExceptionに渡すことで、検証内容ごとにメッセージを切り替えることも可能になります。なお、<h:inputText>などのUIコンポーネントタグ内で定義するvalidatorMessageは、複数の検証機能をまとめて1つのメッセージとしていますので、検証内容によってメッセージを切り替えるといったことはできません。
この検証用メソッドをFaceletsから利用した例が、次のリストとなります。
<h:inputText id="username" value="#{user.username}" validator="#{user.validationUsername}">
</h:inputText>
追加したのはvalidator属性になります。validator属性にて検証機能をメソッドないしはクラスを設けたものを設定させることができます。上のサンプルでは#{user.validationUsername}と設定しています。userはManagedBeanにて先ほど設定した@Namedの名称、そして続けてメソッド名をドット繋ぎで記述することで、そのまま呼び出すことができます。
この記述の方法は、次に紹介する検証用クラスでも同じです。
検証用クラスを設けて利用する方法
複数の画面や入力項目で再利用される検証機能を作成する際に有効となるのが、検証用クラスの作成です。検証用メソッド同様、検証用クラスにも作成ルールに沿って作成します。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
@FacesValidator("sample.emailValidator") …(1)
public class EmailValidator implements Validator { …(2)
/** メールアドレスのフォーマットをチェックする正規表現。 */
private static final String patternString = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
/** 正規表現エンジンクラス */
private Pattern pattern;
/** 正規表現で指定されたパターンに対して文字列をマッチングするためのクラス */
private Matcher matcher;
public EmailValidator(){
// あらかじめ正規表現エンジンのインスタンスを作成。
pattern = Pattern.compile(patternString);
}
/**
* 検証機能用メソッド。
*/
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { …(3)
String email = (String)value;
if ( email == null || "".equals(email)) {
throw new ValidatorException(new FacesMessage("メールアドレスは必須入力です")); …(4)
}
// 正規表現によるチェック。その結果はmatcherインスタンスに格納される
matcher = pattern.matcher(email);
// もし正規表現であわらされたパターンに合致しない場合は検証エラーとする。
if ( !matcher.matches() ){
throw new ValidatorException(new FacesMessage("メールアドレスのフォーマットが正しくありません")); …(5)
}
}
}
では、ソース中に番号で注釈した箇所の説明をしていきます。
- (1)@FacesValidator("sample.emailValidator")。FacesValidatorアノテーションを付けることにより、このクラスはJavaEEコンテナによってJSFの検証機能用クラスとして参照するようになります。()内にてJSFから利用する際の名称を定義します。
- (2)検証用クラスはjavax.faces.validator.Validatorインタフェースを実装する必要があります。
- (3)検証処理を記述するメソッドです。(2)で記載したValidatorインタフェースの実装メソッドになります。引数は検証用メソッド作成したときと同じものを使い、メソッド名はvalidateになります。
- (4)、(5)は、検証内容を記載しているコードです。検証エラーを投げる方法やメッセージを出力する方法はメソッド検証機能と同一です。
この、検証機能クラスを利用するFaceletsのコードは次のようになります。
<h:inputText id="email" value="#{user.email}" validator="sample.emailValidator"> …(1)
<f:ajax render="emailError" event="blur" /> …(2)
</h:inputText>
<h:message for="email" id="emailError" style="color: red"/> …(3)
(1)のvalidator属性にて、先ほど@FacesValidationで指定した名称を指定します。これにより検証機能として先ほどのEMailValidatorクラスのvalidateメソッドが実行されます。
(2)Ajaxを利用した非同期通信を持ちいた検証機能を行います。event="blur"ですので、フォーカスが離れたタイミングで検証機能が実行され、エラーメッセージはrender属性に指定したemailErrorのidを持つ<h:message>に出力されます。このコード内ではすぐ次の行にある(3)となります。
(3)は、メッセージ出力領域です。
