JSF バリデーション

作成 2004/4/26

バリデーションのメモ

バリデーションは、入力値のチェックの仕組みです。 バリデーションはバリデータクラス、あるいはバリデートメソッドを指定することで実行します。 デフォルトのバリデートクラスもいくつかあります。

デフォルトのバリデータ

次の3種類のバリデータはJSFにデフォルトで組み込まれており、 JSPタグ中に指定するだけで利用できます。
クラスタグ
DoubleRangeValidator validateDoubleRange
LengthValidator validateLength
LongRangeValidator validateLongRange

簡単な例

例えば、文字列の長さをチェックするLengthValidatorは次のように使用します。

<h:form>
    <p>a:
    <h:inputText value="#{hoge.s}"
        <f:validateLength maximum="8"/>
    </h:inputText>

    <p><h:commandButton value="GOGO" action="val2"/>

    <p><h:messages/>
</h:form>

実行結果は以下のようになります。バリデーションで、エラーになった場合は、 次の画面に遷移せず(actionは実行されず)、バリデーションのエラーメッセージが表示されます。

必須チェック

必須チェックは、単純にrequired="true"を指定するだけです。

<h:inputText value="#{hoge.s}"
    required="true"/>

メソッドバリデータ

UIInputのタグのvalidate属性にバッキングビーンのメソッドを指定することで、 メソッドによる自作のメソッドによるバリデーションを行うことができます。

<h:inputText value="#{hoge.s}"
    validator="#{hoge.validateS}"/>

メソッドは次のような引数で定義します。

public void validateS(FacesContext context, 
        UIComponent component, Object value){

    String text = value.toString();
    if(text.equals("shit")){
        context.addMessage(component.getClientId(context), 
            new FacesMessage("下品はダメです"));
        ((UIInput)component).setValid(false);
    }
}

この例では、"shit"という文字列が入力値に入力されたとき、バリデーションエラーにしています。 エラーにするには、FacesContext#addMessage(...)でエラーメッセージを設定し、UIInput#setValid(...)で 妥当性をfalseに(バリデーションが失敗した状態に)指定してます。

setValidする方法の他に、以下のようにValidatorExceptionをthrowsしても同様のことが行えます。

public void validateS(FacesContext context, 
        UIComponent component, Object value){

    String text = value.toString();
    if(text.equals("shit")){
        throw new ValidatorException(new FacesMessage("下品はダメです"));
    }
}

メッセージについて

バリデーションだけに関連するのではありませんが、JSFでのメッセージリソースの取り扱いについて簡単にメモしておきます(予定)。

@TODO
メッセージの追加と表示
指定した場所にメッセージを出す
メッセージの日本語化
グローバルメッセージ

カスタムバリデータ

バリデータはクラスとして新たに定義、利用することができます。

バリデータクラス

次のリストはカスタムバリデータクラスの例です。 バリデータクラスはValidatorインターフェイスを実装して作成します。 validateメソッドの中身は、さきほどのメソッドのバリデータとほとんど同じです。

public class BannedWordValidator implements Validator{

    public void validate(FacesContext context, UIComponent component, Object value) 
    throws ValidatorException {

        String text = value.toString();
        if(text.equals("shit")){
            throw new ValidatorException(new FacesMessage("下品はダメです"));
        }
        
    }
}

つっこみいただきました。正しくはStateHolderを実装する必要があるようです(そうしないと困る場面がある)。例えばSTATE_SAVING_METHODをclientにしているとき、RegExpValidator.patternの値がnullになります。Validatorに限らず、カスタムうんぬん作るときは全部ですな。

faces-confix.mlへの登録

作成したバリデータをJSP側から利用するには、faces-config.xmlへ登録します。

<validator>
    <validator-id>BannedWordValidator</validator-id>
    <validator-class>hoge.BannedWordValidator</validator-class>
</validator>

JSP

JSP側は次のようになります。<f:validator>タグを利用します。 validatorIdにはfaces-config.xmlに登録したidを指定します。

<h:inputText value="#{hoge.s}">
    <f:validator validatorId="BannedWordValidator"/>
</h:inputText>

カスタムバリデータタグ

上の例では、JSPからバリデータに何らかのパラメータがわたせません。 パラメータを渡したい場合は、バリデータ用のカスタムタグを作成します。

バリデータクラス

ここで作成するバリデータは正規表現チェックバリデータです。正規表現のパターンを セットできるようにしています。

public class RegExpValidator implements Validator{

    private String pattern;
    
    public void validate(FacesContext context, UIComponent component, Object value) 
    throws ValidatorException {
        String text = value.toString();
        if(!text.matches(pattern)){
            throw new ValidatorException(new FacesMessage("書式が違うかも"));
        }
    }
    
    public void setPattern(String pattern){
        this.pattern = pattern;
    }
}

faces-config.xmlへ登録

このバリデータをfaces-config.xmlに登録します。ここまでは、前の例とほとんど同じですが、 attribute属性に設定できるパラメータを指定しているところが若干異なります。

<validator>
    <validator-id>RegExpValidator</validator-id>
    <validator-class>hoge.RegExpValidator</validator-class>
    <attribute>
        <attribute-name>pattern</attribute-name>
        <attribute-class>java.lang.String</attribute-class>
    </attribute>
</validator>

カスタムタグクラス

このバリデータに対するカスタムタグは次のようになります。 コンストラクタでバリデータのIDをセットし、createValidator()で、バリデータのインスタンスを作成しています。

public class RegExpValidatorTag extends ValidatorTag{

    private String pattern;
    
    public RegExpValidatorTag(){
        setValidatorId("RegExpValidator");
    }
    
    protected Validator createValidator() throws JspException {
        //RegExpValidator validator = new RegExpValidator();
        RegExpValidator validator =  (RegExpValidator)super.createValidator();
        validator.setPattern(pattern);
        return validator;
    }

    public String getPattern() {
        return pattern;
    }

    public void setPattern(String pattern) {
        this.pattern = pattern;
    }
}

TLDファイル

TLDファイルはこうなります。

<tag>
    <name>validateRegExp</name>
    <tag-class>hoge.RegExpValidatorTag</tag-class>
    <attribute>
        <name>pattern</name>
        <required>true</required>
    </attribute>
</tag>

JSP

JSP側は次のようになります。

<%@ taglib uri="WEB-INF/test.tld" prefix="myh" %>

...

<h:inputText value="#{hoge.s}">
    <myh:validateRegExp pattern="^.+@.+$"/>
</h:inputText>

参考

Sun J2EE 1.4 Tutorial
Chapter18 の Using the Standard Validators と Using Custom Objects

cardemoサンプルのFormatValidator

@TODO

複数のUIコンポーネントの複合のバリデートはどこに書くべき?アクション? (ex.入力値の合計が100ポイント以下、AはBより小さい)


Back Top