概要
Bean Validation を使用して入力チェックを行い、エラーメッセージを出力する場合、内容にフィールド名を含ませたい場合は注意が必要だったのでメモ。
実行環境
- java SE - 1.8
- org.springframework - 3.1.1.RELEASE
- javax.validation - 2.0.1.Final
- org.hibernate.validator - 6.0.13.Final
例
以下のフォームに対して次のようなメッセージを出力させたい場合
UserForm.java
import java.io.Serializable;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class UserForm implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull(message = "{userForm.name}")
@Size(min = 1, max = 20, message = "{userForm.name}")
private String name;
// getter/setterは省略
"[name] is not null."
注意点
- LocalValidatorFactoryBeanでは出力できない
UserControl.java
import javax.validation.Validator;
@Resource
private Validator validator;
// 実際の処理部分
Set<ConstraintViolation<UserForm>> violations = validator.validate(form);
if (!violations.isEmpty()) {
for (ConstraintViolation<UserForm> v : violations) {
log.info(v.getMessage());
}
}
application-context.xml
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
ValidationMessage.properties
userForm.name={0} is not null.
{0}がフィールド名に置き換わると思っていたが、実際の出力結果は以下のように置換されず出力されてしまう
{0} is not null.
理由
- フィールド名の置換は、Springが提供するデータバインディングにより実現される模様
つまり、以下のように@Validatedを用いる
UserControl.java
@RequestMapping(value = "create", method = RequestMethod.POST, params = "confirm")
public String createConfirm(@Validated UserForm form, BindingResult result) {
if (result.hasErrors()) {
return "user/createForm";
}
return "user/createConfirm";
}
もしくはSmartValidatorを使う
UserControl.java
import org.springframework.validation.SmartValidator;
@Resource // SmartValidatorは<mvc:annotation-driven>の設定が行われていれば使用できるため、Bean定義不要
private SmartValidator smartValidator;
@RequestMapping(value = "create", method = RequestMethod.POST, params = "confirm")
public String createConfirm(UserForm form, BindingResult result) {
smartValidator.validate(form, result);
if (result.hasErrors()) {
return "user/createForm";
}
return "user/createConfirm";
}
まとめ
- LocalValidatorFactoryBeanでは、エラーメッセージにフィールド名を含んでの出力はできない
- Springのデータバインディングにより実現されるため
- 実現するには@ValidatedやSmartValidatorを用いる
※どうしてもLocalValidatorFactoryBeandでなくてはならないなら、個別でメッセージを定義するとかしかなさそう