Edited at

ValidationMessages.propertiesはクラスパス上に複数あるとダメだよ

More than 1 year has passed since last update.

Bean Validation(以降「BV」)のメッセージ(Hibernate Validator(以降「HV」)などのプロバイダーが提供するデフォルトメッセージ)は、クラスパス直下にValidationMessages.properties(リソースバンドルなので言語毎のファイル)を作成することで変更することができます。

例えば・・・プロバイダとしてHVを利用すると、@Size(VB提供の制約アノテーション)と@Length(HV提供の制約アノテーション)のデフォルトメッセージは以下の通りです。


HVのjarファイル内にあるメッセージ定義

javax.validation.constraints.Size.message = size must be between {min} and {max}

org.hibernate.validator.constraints.Length.message = length must be between {min} and {max}

このメッセージを変更する場合は・・・


src/main/resources/ValidationMessages.properties

javax.validation.constraints.Size.message = 'Size' must be between {min} and {max}.

org.hibernate.validator.constraints.Length.message = 'Length' must be between {min} and {max}.

とすれば任意のメッセージに変更できます。


複数のValidationMessages.propertiesがある状況って?

では、複数のValidationMessages.propertiesがある状況って・・・具体的にはどんなときなのでしょうか?私が関わった案件では、以下の2つのパターンでValidationMessages.propertiesが存在する状況が生まれました。


  • ライブラリとして独自のバリデータを作成しJarファイルの中にValidationMessages.propertiesを格納(してしまった)

  • マルチモジュール構成のプロジェクトで、各モジュール内にValidationMessages.propertiesを格納(してしまった)


BVの仕様的に複数ファイルはサポートしている?

私がBVの仕様書をざっと見た範囲では、複数ファイルについて言及されてなかったので、標準仕様としては複数ファイルをサポートしていない思われます。(英語弱いので読みとしている可能性はあります・・・)


複数あるとどうなるの?

細かい動きはおさえていませんが・・・プロバイダとしてHVを使用すると、いずれか1つのファイルが有効になります。おそらくクラスパスの優先が高いところにあるファイルが使われると思われますが、Webアプリケーション(war)のlibにあるjarファイルのような優先順が明示的に指定できない場合は、アプリケーションサーバの実装などによって有効になるファイルがかわることも予想されます。



結果として、有効にならなかったファイルに指定したメッセージを前提にしているところで想定したメッセージがでなくなります(→つまりバグります)。


BV仕様準拠の対策

BV仕様準拠にこだわる場合は、ライブラリやサブモジュール内のValidationMessages.propertiesを削除し、アプリケーション実行時のクラスパス上にValidationMessages.propertiesが1つになるように制御してください。


HVの機能を使った対策

BV仕様準拠にこだわりがなく+HV上で使うことを前提としている場合は、HV独自のメッセージ定義の読み込み機能の仕組みを使うことができます。

具体的には・・・ライブラリやサブモジュールのJarファイルの直下にはValidationMessages.propertiesではなく、ContributorValidationMessages.propertiesを格納するように変更してください。こうすることで、HVがクラスパス上に存在する全てのContributorValidationMessages.propertiesを読み込んでメッセージを構築してくれるようになります。

HVを使う場合のメッセージ定義の優先順(優先度が高い順に)を整理すると・・・・


  • クラスパス直下のValidationMessages.properties (複数あると1ファイルのみ有効)

  • クラスパス直下のContributorValidationMessages.properties (全ファイル有効)

  • クラスパス上のorg/hibernate/validator/ValidationMessages.properteis(HV提供のデフォルトのメッセージ定義ファイル)

となります。


検証アプリ


まとめ

HV上での使用を前提としたライブラリであれば、デフォルトメッセージはContributorValidationMessages.propertiesに定義して配布するのが良さそう。仮にHV以外のプロバイダ上で使っても悪さしないはずだし・・・。