Develop with pleasure!

福岡でCloudとかBlockchainとか。

バリデーション

Struts2で入力値にバリデーションをかける。基本的な仕組みはStruts Classicの頃と変わっていない。変わったのは、

  • バリデーションの設定ファイルは、Actionと同じ階層で「action名-validation.xml」という命名規則でAction単位に作成する。
  • エラーメッセージを設定するメッセージリソースも、バリデーションの設定ファイルと同様にActionと同じ階層で「action名_ja.properties」というプロパティファイルをAction単位に作成する。


ただ、正直メッセージリソースまでAction単位というのもちょっとうざい。そんな時は、struts.xml

<constant name="struts.custom.i18n.resources" value="MessageResources"/>

といった具合に定義できる。「.properties」は省略可能。複数定義したい場合はカンマ区切りで。

で、当然バリデーションの結果エラーになった戻り先もStruts Classic同様で定義が必要。Actionに

@Results({
    @Result(type = ActionChainResult.class, value = "sample"),
    @Result(name = Action.INPUT, value = "/input.ftl")
})

といった感じで、name="input"(Action.INPUTはcom.opensymphony.xwork2.Actionの定数"input")として遷移先を定義する。アノテーションで定義していない場合は、struts.xmlタグで定義。

エラーメッセージもStruts2のタグにより提供される。ViewにJSPではなくFreeMarkerを使っている場合も、こんな感じ。

メッセージをすべて出力
<@s.fielderror>

メッセージ(フィールドhogeのエラーメッセージ)を個別に出力
<@s.fielderror><@s.param value="%{'hoge'}" /></@s.fielderror>

ちょっと個別のメッセージがタグのネストになっているのが微妙だ…。

まぁ、こういった変更とは別にアノテーションベースになっているので、バリデーションのXML設定ファイルを使わずともAction内のチェック対象であるフィールドsetterにアノテーションを付加することで同様のことが可能になる。ただ、入力値を保持するフィールドがAction内のフィールドであれば、まぁ良いかと思うけど、ModelDrivenインターフェースをActionにimplementsさせ入力値を別のJavaBeansのフィールドに保持させている場合、そのモデルのフィールドのsetterにアノテーションを付加させると、そのモデル自体がStruts2(正確にはWebWork2)に依存してしまう形になる。
折角、外のモデルに出したのであれば、そのモデルはWeb層に依存しない形で実装しService層へ渡したい。いくらアノテーションといっても、結局そのアノテーションがimportされてなければコンパイルエラーになるので、依存性はある。(個人的には、JSR等でJavaの標準として策定されていないアノテーションをセットするというのは、その時点でPOJOでは無いと思う。だからSpringのアノテーションベースのインジェクションにも、@Autowiredは使用せずにJSR-250で定義されている@Resourceを使う方が好きだ。)
と、いうふうに考えると、まぁバリデーションまでアノテーション化する必要は無いかと思う。いくらアノテーションベースになったからと言って、何でもかんでもアノテーションにする必要は無い!