Edited at

Bean Validationにおいて、Error MessageにField Nameを含ませたい場合にLocalValidatorFactoryBeanからでは出力できない


概要

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

:star:SampleProjectをGitHubに置いています


以下のフォームに対して次のようなメッセージを出力させたい場合


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でなくてはならないなら、個別でメッセージを定義するとかしかなさそう