はじめに
Spring Bootを使ったWebアプリケーション開発において、フォーム入力値のバリデーションは欠かせません。
しかし、バリデーションの実装によっては意図しない例外が発生しエラーハンドリングが適切に行われないことがあります。
本記事では、Spring Bootで発生したバリデーションエラーに関する問題とその解決策を紹介します。
発生した問題
バリデーションルールを設定したフォームで、特定の条件を満たさない入力が行われた際に、想定外の例外が発生するように処理していました。その際に、適切なエラーハンドリングが行われないケースがありました。
具体的には、
- @Validを使用してバリデーションを実施しているが、エラーメッセージが適切に表示されない。
- ConstraintValidatorを実装したクラス内で RuntimeExceptionをスローすると、Springの@ExceptionHandlerで適切に処理されない。
- エラー時に、想定していたカスタム例外ではなく ValidationException に変換されてしまう。
原因
この問題の原因として、以下の点が挙げられます。
- ConstraintValidator内でRuntimeExceptionをスローしていた。
- ConstraintValidatorはConstraintViolationExceptionを利用する前提のため、RuntimeExceptionをスローするとValidationExceptionに変換され、カスタム例外で処理できなくなっていた。
解決策
1. ConstraintValidator内でRuntimeExceptionをスローしない
適切なエラーハンドリングを行うために、ConstraintValidatorContextを使用してbuildConstraintViolationWithTemplateを使う。
@Override
public boolean isValid(CustomForm form, ConstraintValidatorContext context) {
if (form.getField() == null || form.getField().isEmpty()) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("入力値が不正です")
.addConstraintViolation();
return false;
}
return true;
}
2. @ExceptionHandlerでValidationExceptionを適切に処理する
ValidationExceptionを捕捉し、適切なリダイレクトやエラーメッセージの表示を行う。
@ExceptionHandler(ValidationException.class)
public String handleValidationException(ValidationException ex, RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("errorMessage", ex.getMessage());
return "index";
}
他の方法
-
Spring の @Validated を使用する
コントローラーで @Validated を使用し、BindingResult でバリデーションエラーを処理する。 -
カスタムアノテーションを作成する
より細かいバリデーションを行いたい場合は、独自のバリデーションアノテーションを作成する。
まとめ
今回は、ConstraintValidatorがあるところでRuntimeExceptionの例外をスローすると、本来のConstraitValidator側で処理しきれずRuntimeExceptionになっていたようです。
今回はアノテーションで処理せずカスタムバリエーションを使用したかったので少し悩みました。
Spring Booのバリデーションエラーの処理では、ConstraintValidator内でRuntimeExceptionをスローしないことが解決の鍵でした。ご参考になれば幸いです。