LoginSignup
10
11

More than 5 years have passed since last update.

Hibernate ValidatorでValidationMessages.properties以外のファイルを使う

Last updated at Posted at 2015-09-03

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 が言語に応じて読み込まれてメッセージに使用されます。

CustomMessageInterpolator.java
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ひっさびさすぎてやばい

10
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
11