Spring の @Validated と Bean Validation の javax.validation.groups.Default と groups について

実際の挙動がイメージとちょっと違うのでメモる。

パターン1

バリデーショングループのインタフェースで javax.validation.groups.Default を継承しないパターン。

interface Group {}

@NotNull
private String foo;
@NotNull(groups = Group.class)
private String bar;

Controller で @Validated とする場合、groups が未指定 or Default.class を指定したアノテーションのフィールドがバリデーション対象になる。ここでは foo のバリデーションが実行される。

一方、Controller で @Validated(Group.class) とする場合、Group.class を指定したアノテーションのフィールドがバリデーション対象になる。ここでは bar のバリデーションが実行される。

パターン2

バリデーショングループのインタフェースで javax.validation.groups.Default を継承するパターン。

interface Group extends Default {}

@NotNull
private String foo;
@NotNull(groups = Group.class)
private String bar;

Controller で @Validated とする場合、groups が未指定 or Default.class を指定したアノテーションのフィールドがバリデーション対象になる。ここでは foo のバリデーションが実行される。

一方、Controller で @Validated(Group.class) とする場合、Group.class を指定したアノテーションgroups が未指定 or Default.class を指定したアノテーションのフィールドがバリデーションの対象になる。ここでは foobar のバリデーションが実行される。

まとめ

当初、パターン2の挙動がイメージと違ってたんですが、こうやってまとめてみると別におかしくないですね...。Group インタフェースは Default インタフェースのサブインタフェースなので、is-a の関係になります。なので、パターン2において、Default を指定したときは Group.classアノテーションは対象外になるし、Group を指定したときは Default.classGroup.classアノテーションが対象になるのは当たり前ですね。