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】validation コードを Violations クラスでスッキリ書こう

0
Posted at

結論

ecuacion-lib-validationViolations クラスを使うと、Jakarta Validation の validation コードをメソッドチェーンでシンプルに書けます、というお話。

はじめに

ecuacion-lib-validation ではメッセージのカスタマイズに Violations.newMessageParameters()ConstraintViolationExceptionWithParameters を使用します。

例えば、パラメータなしでエラー時に例外をスローする場合のコードはこちら。

  Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
  var constraintViolations = validator.validate(form);
  if (constraintViolations.size() > 0) {
    throw new ConstraintViolationException(constraintViolations);
  }

これはそれほど問題ないですが、メッセージパラメータを指定したい場合はこうなります。

  Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
  var params = Violations.newMessageParameters().isMessageWithItemName(true);
  var constraintViolations = validator.validate(form);
  if (constraintViolations.size() > 0) {
    throw new ConstraintViolationExceptionWithParameters(constraintViolations, params);
  }

これが毎回あちこちに書かれると、少々冗長に感じますね。

Violations クラスの使い方

ecuacion-lib-validation の導入方法

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

パラメータなし(基本形)

冒頭の4行のコードが、こう書けます。

  new Violations().addAll(validator.validate(form)).throwIfAny();

new Violations() でオブジェクトを生成、addAll で validate の結果を追加、throwIfAny でエラーがあれば例外をスローします。

メッセージパラメータを指定する場合

メッセージパラメータを指定したい場合は、withMessageParameters を使用します。

  new Violations().addAll(validator.validate(form))
      .withMessageParameters(p -> p.isMessageWithItemName(true))
      .throwIfAny();

withMessageParameters の引数はラムダ式で MessageParameters を操作します。複数のパラメータも連鎖して書けます。

  new Violations().addAll(validator.validate(form))
      .withMessageParameters(p -> p
          .isMessageWithItemName(true)
          .messagePrefix("アップロードしたエクセルファイルにおいて、"))
      .throwIfAny();

BusinessViolation との併用

Violations クラスは、Jakarta Validation の ConstraintViolation だけでなく、BusinessViolation(ビジネスロジック上のエラー)も同じオブジェクトにまとめて扱えます。

BusinessViolation は、「このメールアドレスはすでに登録済みです」のような、入力形式ではなくビジネスルール上のエラーを表すクラスです。

  Violations violations = new Violations()
      .addAll(validator.validate(form));

  // ビジネスロジックのチェック
  if (accountRepository.existsByEmail(form.email())) {
    violations.add(new BusinessViolation("このメールアドレスはすでに登録済みです。"));
  }

  violations.throwIfAny();

Jakarta Validation のエラーとビジネスロジックのエラーを1つの Violations にまとめてから一括で throwIfAny できるので、ExceptionHandler 側での処理も統一できます。

まとめ

Violations クラスを使うと、validation のコードがメソッドチェーンでスッキリ書けます。

パターン 通常の書き方 Violations を使った書き方
パラメータなし validate → サイズチェック → throw new Violations().addAll(...).throwIfAny()
パラメータあり params 生成 → validate → サイズチェック → throw new Violations().addAll(...).withMessageParameters(...).throwIfAny()
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?