Hibernate Validatorは相変わらず便利
こうしきさいと: Hibernate Validator
ValidationMessages.properties一つでは無理ぽ
Hibernate Validatorではライブラリのデフォルトの ValidationMessages.properties
や、ユーザー指定の /path/to/resources/ValidationMessages.properties
がデフォルトで使用されます。
というわけで、普通に使っていたら他の *.properties
を使えません。
特段困ることはありませんが、肥大化して ValidationMessages.properties
だけでは管理が面倒になる未来が見えてくることがあります。全メッセージを(言語別とはいえ)一つのファイルにまとめているとキモい展開に...というのが嫌だったので作りました。下記の例では /path/to/resources/com/example/hoge/dto/FormData/ValidationMessages.properties
が言語に応じて読み込まれてメッセージに使用されます。
package com.example.hoge;
import java.util.Locale;
import javax.validation.MessageInterpolator;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator;
public class CustomMessageInterpolator implements MessageInterpolator {
private Locale locale;
private MessageInterpolator mi;
public CustomMessageInterpolator(String resourceName) {
this.locale = null;
this.mi = new ResourceBundleMessageInterpolator(
new PlatformResourceBundleLocator(resourceName)
);
}
public CustomMessageInterpolator(String resourceName, Locale locale) {
this.locale = locale;
this.mi = new ResourceBundleMessageInterpolator(
new PlatformResourceBundleLocator(resourceName)
);
}
@Override
public String interpolate(String m, Context c) {
return this.locale == null ?
mi.interpolate(m, c) :
mi.interpolate(m, c, this.locale);
}
@Override
public String interpolate(String m, Context c, Locale l) {
// 引数のLocaleを使用するとシステムのLocaleが使われてしまい、
// コンストラクタで指定したLocaleが効かない
return this.locale == null ?
mi.interpolate(m, c, l) :
mi.interpolate(m, c, this.locale);
}
}
こんな感じで使います。言語別にする必要がなければLocale不要版を使用すればOKですね。
import com.example.hoge.CustomMessageInterpolator;
import com.example.hoge.dto.FormData;
import java.util.Locale;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import lombok.extern.slf4j.Slf4j;
(略)
// lang は ja とか en とかそういうの
// formData は JavaBean をよしなに用意
Validator validator = Validation.byDefaultProvider().configure().messageInterpolator(
new CustomMessageInterpolator(
"com.example.hoge.dto.FormData.ValidationMessages", new Locale(lang)
)
).buildValidatorFactory().getValidator();
// validation
Set<ConstraintViolation<FormData>> constraintViolations =
validator.validate(formData, formData.validateGroups());
if (constraintViolations.size() > 0) {
for (ConstraintViolation<FormData> con : constraintViolations) {
// getPropertyPath -> プロパティ名, getMessage -> エラーメッセージ
log.warn(con.getPropertyPath().toString() + "=" + con.getMessage());
}
}
(略)
※しれっと formData.validateGroups()
とか書いてますが「項目Aが選択されてたら項目Bは必須」のようなバリデーションに使うアレのためのものです。あんまり見かけないのでまた別の記事にしようかと思います。
参考情報はこの辺りに↓↓
Validating groups - Hibernate Validate
参考
Hibernate Validatorでエラーメッセージを多言語対応する: nonkiのブログ
おわりに
Javaひっさびさすぎてやばい