Name
Password

バリデーション

  • 2008-09-16 12:56:02

Pageコンポーネントのアクション呼び出しの際にリクエストパラメータが正当であるかどうかを検証することができます。この処理を「パラメータチェック」または「バリデーション」と呼びます。Ymirではバリデーションは「制約チェック」の一種です(他の制約チェックの種類としては「権限チェック」があります)。

バリデーションの指定

バリデーションを指定するにはアノテーションを用います。詳細については「制約の指定」を参照して下さい。

処理の詳細

バリデーションはPageコンポーネントへの依存コンポーネントやリクエストパラメータがセットされた後、アクション呼び出しの前に行なわれます。バリデーションに失敗すると、アクションを呼び出す代わりに以下の処理が行なわれます。

  1. バリデーション失敗に関する詳細情報であるorg.seasar.ymir.Notesオブジェクトが「notes」というキーでHttpServletRequestオブジェクトのアトリビュートとしてセットされる。
  2. Pageコンポーネントが_validationFailed(Notes)メソッドを持っている場合、1.で生成されたNotesオブジェクトを引数としてこのメソッドが呼び出される。なければ_validationFailed()メソッドがあれば呼び出される。

なお、_validationFailedメソッドの呼び出しが行なわれた場合でも行なわれなかった場合でも_renderメソッドは呼び出されます。

Notesオブジェクト

バリデーションに失敗した場合、その情報がorg.seasar.ymir.Notesオブジェクトにセットされます。バリデーションのためのアノテーションが複数指定されている場合は全てのバリデーションが行なわれ、失敗したものについてNotesオブジェクトに情報がセットされます。

Notesオブジェクトは1つまたは複数のorg.seasar.ymir.Noteオブジェクトをカテゴリ毎に保持しています。Noteオブジェクトはvalueとパラメータを保持しています。StrutsのActionMessagesとActionMessageと同じようなものと思っていただければいいと思います。

Note#getValue()の値(noteキー)はバリデーションの種類によって異なりますので、これを見ることで失敗したバリデーションが何か知ることができます。

バリデーション失敗に関するNoteオブジェクトは、そのバリデーションの対象であるリクエストパラメータ名と同じ名前のカテゴリに関連付けられてNotesオブジェクトに追加されます。

メッセージの表示

バリデーションエラーメッセージを表示するには、例えば以下のようにします。

まとめて表示する場合、

<ul tal:condition="notes">
  <li tal:repeat="note notes/notes" tal:content="note/%value">MESSAGE</li>
</ul>

全体に関するメッセージを先頭に表示し、項目ごとのメッセージ項目ごとに表示する場合、

<ul tal:condition="notes/size(org.seasar.ymir.GLOBAL_NOTE)">
  <li tal:repeat="note notes/org.seasar.ymir.GLOBAL_NOTE" tal:content="note/%value">GLOBAL MESSAGE</li>
</ul>
...
<ul tal:condition="notes/size(param)">
  <li tal:repeat="note notes/param" tal:content="note/%value">MESSAGE FOR PARAM</li>
</ul>

メッセージのカスタマイズ

表示されるメッセージをカスタマイズするには、アプリケーションのsrc/main/resourcesにあるmessages.xpropertiesに書かれているプロパティのうち、noteキーと同じキーを持つものを変更して下さい。

バリデーションの種類

Ymirが標準で提供しているバリデーションは以下のとおりです。(アノテーションクラスはorg.seasar.ymir.constraint.annotationパッケージにあります。)

アノテーション名 説明
Length

リクエストパラメータ文字列の長さに関する制約を指定します。

制約の対象となるのは、propertyプロパティで指定されたリクエストパラメータと、アノテーションが付与されているSetterから導き出せるプロパティ名と同名のリクエストパラメータです。

noteキーはerror.constraint.lengthです。

指定できるプロパティは以下のとおりです。

property
対象となるリクエストパラメータ名。複数指定可能。
min
長さがここで指定したのと同じか長い必要があることを表します。
max, value
長さがここで指定したのと同じか短い必要があることを表します。valueよりもmaxの方が優先されます。
Numeric

リクエストパラメータが数値として解釈可能であるという制約を指定します。

制約の対象となるのは、valueプロパティとpropertyプロパティで指定されたリクエストパラメータと、アノテーションが付与されているSetterから導き出せるプロパティ名と同名のリクエストパラメータです。

noteキーはerror.constraint.numericです。

指定できるプロパティは以下のとおりです。

value
対象となるリクエストパラメータ名。
property
対象となるリクエストパラメータ名。複数指定可能。
integer
値が整数値である必要があることを表します。デフォルトの値はtrueです。
greaterThan
値がここで指定したよりも大きい必要があることを表します。
greaterEqual
値がここで指定したのと同じか大きい必要があることを表します。
lessThan
値がここで指定したよりも小さい必要があることを表します。
lessEqual
値がここで指定したのと同じか小さい必要があることを表します。
Required

リクエストパラメータが必須である(nullや空文字列ではない)という制約を表します。

制約の対象となるのは、valueプロパティで指定されたリクエストパラメータと、アノテーションが付与されているSetterから導き出せるプロパティ名と同名のリクエストパラメータです。

noteキーはerror.constraint.requiredです。

指定できるプロパティは以下のとおりです。

value
対象となるリクエストパラメータ名。複数指定可能。
completely
同一名のパラメータが複数指定されている場合に、全てのパラメータが埋まっているべきかどうか。デフォルトはfalse。falseの場合は、複数のうちどれか1つだけでも埋まっていればバリデーションエラーにならない。
allowWhitespace
パラメータが空白文字(半角スペース、タブ、改行)だけからなる文字列を許容するかどうか。デフォルトはtrue。falseにすると、空白文字だけからなる文字列をバリデーションエラーとみなすようになる。
TokenRequired

リクエストパラメータとして渡されたトランザクショントークンがセッションに保持されているものと一致する必要があることを表します。

このアノテーションはクラスまたはアクションメソッドに付与して下さい。

noteキーはerror.constraint.tokenRequiredです。

指定できるプロパティは以下のとおりです。

value
トークンを保持しているリクエストパラメータ名。省略した場合はデフォルトの名前が参照されます。

ページ固有のバリデーション

独自にバリデーションのためのアノテーションと処理クラスを作成することでアプリケーション固有のバリデーションを実現することができますが、ページ固有のバリデーションの場合はわざわざアノテーションと処理クラスを作るのは大変です。そこでYmirでは、ページ固有のバリデーションをPageクラス内に書くことができるようになっています。

具体的には、返り値がorg.seasar.ymir.Notesであるようなメソッドまたはorg.seasar.ymir.constraint.ValidationFailedExceptionをスローするような返り値がvoidであるメソッドをPageクラスに追加して、org.seasar.ymir.annotation.Validatorアノテーションを付与することで、そのメソッドがバリデーションの際に呼び出されるようになります。

形式1:

@Validator
public Notes validate()
{
    if ([バリデーション失敗]) {
        return new Notes().add([リクエストパラメータ名], new Note(
            Constraint.PREFIX_MESSAGEKEY + [バリデート種別],
            new Object[]{ [リクエストパラメータ名] }));
    } else {
        return null;
    }
}

形式2:

@Validator
public void validate() throws ValidationFailedException
{
    if ([バリデーション失敗]) {
        throw new ValidationFailedException(
            new Notes().add([リクエストパラメータ名], new Note(
                Constraint.PREFIX_MESSAGEKEY + [バリデート種別],
                new Object[]{ [リクエストパラメータ名] })));
    }
}

バリデーションに失敗した場合は、返り値またはValidationFailedExceptionのコンストラクタの引数として、失敗情報に対応するNoteオブジェクトを含むようなNotesオブジェクトを指定するようにして下さい。バリデーションに成功した場合は、返り値がNotesのメソッドの場合は空のNotesオブジェクトを返すかnullを返すようにして下さい。

ボタンに関連付けられたアクションが呼び出されるケースでボタン名にパラメータが埋め込まれている場合、バリデータメソッドにも引数としてアクションに渡されるのと同じパラメータが渡されますので、パラメータを受けたい場合はバリデータメソッドに引数を定義して下さい。その際、それぞれの引数の型はアクションメソッドと同一にして下さい。

@Validatorアノテーションは複数のメソッドに付与することができます。また、あるアクションが呼び出される時だけバリデーションメソッドを動作させたい場合は、アノテーションの引数としてアクションメソッド名を列挙して下さい。アクションメソッド名を指定しない場合は全てのアクションに関してバリデーションが有効になります。