Spring Batchで「Hibernate Validator」を使うと日本語化がうまく出来ない

Spring Batchとは

  • バッチ処理を行う「バッチアプリケーションフレームワーク」

Spring Bootで開発を行っている中、Spring Batchでバッチを用いて実装したりしてます。

その最中、Hibernate Validation(Bean Validation)を使ったバリデーション処理のエラーメッセージ日本語化で結構ハマったのでメモします。

スポンサーリンク

環境情報

  • gradleVersion = ‘4.10.2’
  • org.springframework.boot:spring-boot-starter-batch -> 1.5.13.RELEASE

Spring Batch & Hibernate Validatior 導入

「Spring Batch」と「Hibernate Validatior」を使うには以下のようにします。

「build.gradle」

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-batch'
    compile 'org.hibernate:hibernate-validator'
    // 略
}

このバッチ処理内で何かバリデーションを実装したい時があります。
ロジックを書かずに手軽に実装するためHibernate Validatior を使ってみます。

package moge.moge

import org.hibernate.validator.constraints.NotBlank
// 略

class HogeHoge(
    @get:NotBlank
    var loginId: String,
    @get:NotBlank
    var password: String,
// 略

Validatorを使う細かい設定は省略してますが、

@get:NotBlank

上記のようなアノテーション付与でNotBlankのバリデーションを掛けることが出来ます。
簡単に使えるすごい奴です。

日本語メッセージ化

バリデーションメッセージは何も手を付けなければ英語で出力されます。

hibernate-validator/ValidationMessages.properties / GitHub

Not Blankだと
「must not be blank」
といった感じです。

これは日本語のresourcesファイルを作ることで、オーバーライドして日本語化出来ます。

/hogehoge-batch/src/main/resources/i18n/ValidationMessages_ja_JP.properties

org.hibernate.validator.constraints.NotBlank.message=入力必須項目です。

これでエラーメッセージが日本語化されます。

Spring Batchだと日本語化されない?

本題です。

上記の設定を行うことによって日本語化されるはず・・・

が、Spring Batchで日本語化がうまく行きません。
オーバーライドしたはずが、日本語メッセージが表示されません。

試しに「spring-boot-starter-web」を依存関係に追加しているWebアプリの方で、同様の設定を試してみました。
すると、うまく日本語化出来ています。これはSpring Batchの方に何か問題がありそうです。

調べてみると関連がありそうなものを見つけました。

Bean Validation 1.1(Hibernate Validator 5.x)以上を使用する場合、 Bean ValidationのAPI仕様クラス(javax.validationパッケージのクラス)が格納されているjarファイルとHibernate Validatorのjarファイルに加えて、

  • Expression Language 2.2以上のAPI仕様クラス (javax.elパッケージのクラス)
  • Expression Language 2.2以上のリファレンス実装クラス

が格納されているライブラリが必要となる。

アプリケーションサーバにデプロイして動かす場合は、 これらのライブラリはアプリケーションサーバから提供されているため、 依存ライブラリの追加は不要である。 ただし、スタンドアロン環境(JUnitなど)で動かす場合は、これらのライブラリを依存ライブラリとして追加する必要がある。

4.1. 入力チェック — TERASOLUNA Server Framework for Java (5.x) Development Guideline 5.4.1.RELEASE documentation

Hibernate Validatorを使うには?

つまり、Hibernate Validatorを使う場合、

  • Expression Language 2.2以上のAPI仕様クラス (javax.elパッケージのクラス)
  • Expression Language 2.2以上のリファレンス実装クラス

が追加されているか確認する必要がある。

また、

tomcat-embed-elのjarファイルには、Expression LanguageのAPI仕様クラスとリファレンス実装クラスの両方が格納されている

と、あるのでtomcat-embed-elの存在を確認してみましょう。

spring-boot-starter-batch

早速spring-boot-starter-batchで追加される依存関係を確認。

+--- org.springframework.boot:spring-boot-starter-batch -> 1.5.13.RELEASE
|    +--- org.springframework.boot:spring-boot-starter:1.5.13.RELEASE (*)
|    +--- org.springframework.boot:spring-boot-starter-jdbc:1.5.13.RELEASE (*)
|    \--- org.springframework.batch:spring-batch-core:3.0.9.RELEASE
|         +--- com.ibm.jbatch:com.ibm.jbatch-tck-spi:1.0
|         |    \--- javax.batch:javax.batch-api:1.0
|         +--- com.thoughtworks.xstream:xstream:1.4.7
|         |    +--- xmlpull:xmlpull:1.1.3.1
|         |    \--- xpp3:xpp3_min:1.1.4c
// 略

tomcat関係は追加されないので、当然tomcat-embed-elは存在しない

spring-boot-starter-web

一方Webアプリで使っているspring-boot-starter-webを追加した場合を確認する。

+--- org.springframework.boot:spring-boot-starter-web -> 1.5.13.RELEASE
|    +--- org.springframework.boot:spring-boot-starter:1.5.13.RELEASE (*)
|    +--- org.springframework.boot:spring-boot-starter-tomcat:1.5.13.RELEASE
|    |    +--- org.apache.tomcat.embed:tomcat-embed-core:8.5.31 (*)
|    |    +--- org.apache.tomcat.embed:tomcat-embed-el:8.5.31
|    |    \--- org.apache.tomcat.embed:tomcat-embed-websocket:8.5.31
|    |         \--- org.apache.tomcat.embed:tomcat-embed-core:8.5.31 (*)
|    +--- org.hibernate:hibernate-validator:5.3.6.Final (*)

なるほど、ちゃんとtomcat-embed-elが追加されている。
つまり、Spring Batchの方ではExpression Languageが存在しない状態で動かしている。

解決方法

「org.apache.tomcat.embed:tomcat-embed-el」を依存関係に追加する

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-batch'
    compile 'org.hibernate:hibernate-validator'
        compile 'org.apache.tomcat.embed:tomcat-embed-el' // 追加
    // 略
}

spring-boot-starter-webで日本語化が出来ていた理由

  • tomcat-embed-elが追加されていたため。

spring-boot-starter-batchで日本語化するには

  • 手動で依存関係を追加する必要がある。

何故こういう事になっているのか分からないですが、これで日本語化出来ます。
手動で依存関係を追加しなくてもバリデーション自体は動くので、結構ハマりました。

おしまい!

参考サイト

Bean Validationで簡単入力チェック!/ @5zm

4.1. 入力チェック — TERASOLUNA Server Framework for Java (5.x) Development Guideline 5.4.1.RELEASE documentation

javax.validation.ValidationException: HV000183: Unable to load ‘javax.el.ExpressionFactory’ / stackoverflow

EL dependencies missing in spring-boot-starter / spring-projects/spring-boot

BeanValidationで日本語メッセージを出力する / 見習いプログラミング日記

Spring Boot Batch Starter / Maven Repository