SAStrutsの入力チェックの順序

SAStrutsの入力チェックの実装手段は以下の3つがある。

1)アノテーション…入力項目ごとに複数定義できる。
2)検証用メソッド…ひとつのアクションごとに複数定義できる。
3)アクションメソッド…アクションに対して定義できる。

1,2,3の順序

デフォルトでは、入力チェックの順序は、1 -> 2-> 3 の順になる。

1と2の順序は、Excecuteアノテーションのvalidateで、順序の入れ替えができる。

デフォルトでは、1、2、3 は、その前段でエラーが発生したら、次のチェックは実施されない。
ただし、ExcecuteアノテーションのstopOnvalidationErrorで変更できる。

3は、1,2の入力チェックが全てOKのときだけ実行される。

2が複数あるときの順序

2 が複数ある場合は、Excecuteアノテーションのvalidateで順序が指定できる。

2が複数あるとき、デフォルトでは、その前段でエラーが発生したら、次のチェックは実施されない。
ただし、ExcecuteアノテーションのstopOnvalidationErrorで変更できる。

1が複数あるときの順序

アノテーションの実行順に関しては、2つに分けて考える。
1-1) 項目(メンバ変数)ごとの順序
1-2) アノテーションごとの順序

1-1) 項目(メンバ変数)ごとの順序

Javaのソース上のメンバ変数の定義順で入力チェックが実行される。

そして、入力チェックのエラーが複数ある時は、すべてのメッセージが画面に表示される。

画面の表示順は、入力チェックの実行順(つまり、メンバ変数の定義順)になる。

ただし、メンバ変数の順序は、SunのJVMが、たまたまそう動くだけで、その順序が保障されているわけではない。

途中で入力エラーになっても、すべてのメンバ変数で入力チェックが実施される。(この挙動は変更できなそう。)

エラーメッセージの実行順は、org.seasar.struts.customizer.ActionCustomizer#setupValidator の中で、メンバ変数と、アノテーションでforで回しながら、入力チェックのコンフィグ情報を構築しているところがあるので、この部分をいじるのが手っ取り早そう。(実行順を変えれば、表示順も同じように変わる。)

エラーメッセージの表示順だけの変更なら、html:errors タグを使っているなら、org.apache.struts.taglib.html.ErrorsTag をいじってしまうのが手っ取り早い。
ちなみに、エラーメッセージそのものは、org.apache.struts.action.ERROR で、requrest の属性に設定されている。

1-2) アノテーションごとの順序

項目(メンバ変数)に対して、複数のアノテーションをつけているときは、Javaソース上のアノテーションの定義順で
入力チェックが実行される。

そして、入力チェックのエラーが複数ある時は、すべてのメッセージが画面に表示される。

画面の表示順は、入力チェックの実行順(つまりアノテーションの定義順)になる。

ただし、これもメンバ変数と同じで保障されているわけではない。

実行順や、表示順の変え方は、1-1 と同じ。

空文字入力時の入力チェックの挙動

デフォルトで用意されているバリデータアノテーションは、空文字が入力されたとき、
Required アノテーション -> 入力エラー
Required 以外 -> 入力OK
になる。

例えば、

    @Required
    @MaxLength(maxlength="32")
    @Mask(mask="^[0-9]+$")
    public hoge;

としているとき、hoge に入力がないときは、Requiredアノテーションだけ入力エラーになる。

一見、MaxLengthアノテーションや、Maskアノテーションでもエラーになるように見える。

これは、Requiredアノテーションがエラーになったから、次のMaxLength、Maskが実行されなかったわけではない。

MaxLength、Mask は実行されるが、空文字が入力されたときは、強制的に、入力OKとしているため、Required だけ入力エラーが発生することになる。

この辺は、org.apache.struts.validator.FieldChecks の中の、GenericValidator.isBlankOrNull() を使っている部分をみればわかる。

validateMaskは、isBlankOrNull が true のときは、チェックをせずにそのまま終了している。
(今気づいたけど、validateMaxLength の実装は怪しい。空文字確認を、isBlankOrNull ではなくて、value != null でチェックしている。。)

まとめ

特にあれこれしていない限りは、SAStruts の入力チェックの挙動は以下のようになる。

1) 複数のメンバ変数があるときは、メンバ変数の定義順に 実行される。
2) メンバ変数に複数のアノテーションがあるときは、 アノテーションの定義順に実行される。
4)定義されているアノテーションは、常に全て実行され、Requiredアノテーション以外は、空文字は入力OKになる。
5)複数の入力エラーがあるとき、画面の表示順は、実行順と同じになるが、保障されているわけではない。
6)検証メソッドは、アノテーションのチェックがすべて成功したら実行される。
7)アクションメソッドは、アノテーション、検証メソッドのチェックがすべて成功したら実行される。