0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Jakarta Validation】子・孫オブジェクトのエラーメッセージにもわかりやすい項目名をつけたい!

0
Last updated at Posted at 2026-04-12

結論

ecuacion-lib-validation には、@Valid を使って子・孫オブジェクトを検証した場合に、「社員のノートPC」の「機種名」のように、どのオブジェクトに属する項目かを明示したメッセージを生成する機能があります、というお話。

はじめに

Jakarta Validation では、@Valid を使うと子・孫オブジェクトのフィールドまで再帰的に検証できます。

例えばこんな構成を考えてみます。

Employee.java
public record Employee(String name, @Valid Laptop laptop, @Valid CellPhone cellPhone) {
}
Laptop.java
public record Laptop(@NotNull String model) {
}
CellPhone.java
public record CellPhone(@NotNull String model) {
}

EmployeeLaptop(ノートPC)と CellPhone(携帯電話)を持っていて、どちらも model(機種名)フィールドを持っています。

何が問題になるのか

item_names.properties に項目名を登録する際、laptop.model に「機種名」と定義したとします。

item_names.properties
laptop.model=機種名
cellPhone.model=機種名

Laptop 単体で検証するならこれで問題ありません。

出力結果(Laptop 単体で検証した場合)
「機種名」は入力必須です。

一方、Employee を検証した場合、ConstraintViolationpropertyPathemployee.laptop.model になります。

普通に Employee を検証してメッセージを出すと、同じメッセージが出力されます。

出力結果
「機種名」は入力必須です。

どちらのオブジェクトの model がエラーなのか、これだけではわかりません。

LaptopCellPhone のどちらも model フィールドを持っており、どちらもラベルは「機種名」。
これでは「どちらの機種名?」となってしまいます。

「社員のノートPC の」のような文言が必要

エラー内容をユーザに伝えるには、「社員のノートPC の機種名」のように、対象オブジェクトを特定できる文言が必要ですね。

ecuacion-lib-validation では、この問題を ValidationUtil.messageParameters().showsItemNamePath(true) で解決できます。

基本的な使い方

ecuacion-lib-validation の導入方法

導入方法については下記記事をご参照ください。

item_names.properties の定義

showsItemNamePath(true) を使う場合、propertyPath の末尾セグメントに加えて、その親パスの項目名も item_names.properties に定義します。

employee.laptop.model の場合:

  • 親パス employee.laptop に対して employee.laptop=社員のノートPC
  • 末尾セグメントに対して laptop.model=機種名
item_names.properties
employee.laptop=社員のノートPC
employee.cellPhone=社員の携帯電話
laptop.model=機種名
cellPhone.model=機種名

検証コード

ValidationUtil.messageParameters().showsItemNamePath(true) を指定して検証します。

Main.java(一部抜粋)
  public static void showsItemNamePathの使い方() {
    Employee employee = new Employee("山田太郎", new Laptop(null), new CellPhone(null));

    try {
      MessageParameters params = ValidationUtil.messageParameters()
          .isMessageWithItemName(true)
          .showsItemNamePath(true);
      ValidationUtil.validateThenThrow(employee, params);

    } catch (ConstraintViolationException ex) {
      for (String message : ExceptionUtil.getMessageList(ex, false)) {
        System.out.println(message);
      }
    }
  }

出力結果はこちらです。

出力結果
「社員の携帯電話」の「機種名」は入力必須です。
「社員のノートPC」の「機種名」は入力必須です。

親パスの項目名と末尾の項目名を でつなげて表示してくれます。

「社員のノートPC の機種名」なのか「社員の携帯電話の機種名」なのか、明確にわかるようになりましたね。

サンプルコード

サンプルコードは以下です。
https://github.com/ecuacion-jp/ecuacion-code-snippets/tree/main/ecuacion-lib-validation-ValidChildObjectItemNamePath

※このページから直接ソースの zip を download はできないと思うので、そのページにある ecuacion-code-snippets のリンクをクリックし、そこにある緑の <> Code ボタンから Download ZIP で download してください。

本サンプルのフォルダに移動後、mvn compile exec:java で実行できます。

まとめ

@Valid で子・孫オブジェクトを検証した際、同名フィールドが複数存在するとメッセージだけでは対象を特定できなくなります。

ValidationUtil.messageParameters().showsItemNamePath(true) を使うことで、親パスの項目名と末尾の項目名を組み合わせたメッセージが生成でき、「どのオブジェクトの、どのフィールドのエラーか」がユーザに伝わるメッセージになります。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?