2
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?

Thymeleafのバリデーションエラー時にIllegalStateException発生した

Last updated at Posted at 2024-09-27

解決法

自分で考えた解

th:objectに入れる変数を、バリデートを設定しているクラス名(キャメルケース)に合わせる

コメントでいただいた解法

「追記:コメントから」の項目とコメント参照

事象

  • 以下1~3を実装し、バリデートにかかる状態で「登録」を押すと例外が発生してしまった
  • 例外は java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'newForm' available as request attribute(newFormがダメなようなエラー)

修正前の実装

1. Formクラス

  • nameに「1以下のサイズを許可」するバリデートを設定
@Data
public class SampleForm {
	@Size(max = 1)
	private String name;
}

2. Controllerクラス

  • 1.のFormクラスを使って画面表示と入力内容の取得をしている
  • Formクラスは「newForm」という属性名になっている
	//新規登録画面を表示
	@GetMapping("/sample")
	public String displayadd(Model model) {
		model.addAttribute("newForm", new SampleForm());

		return "common/sample";
	}

	//新規登録処理
	@PostMapping("/sample/create")
	public String createUser(@Validated SampleForm newForm, BindingResult result, Model model) {
		if (result.hasErrors()) {
            // バリデートにかかったら元の画面を表示
			return "common/sample";
		}

		//	新規登録する処理を入れる
		return "complete";
	}

3. 新規登録画面html(thymeleaf)

<form th:object="${newForm}">
	<div>
		<input type="text" th:field="*{name}">
		<div th:errors="*{name}"></div>
	</div>
	<input type="submit" th:formaction="@{/sample/create}" th:formmethod="post" value="登録">
</form>

修正方法

  • 以下のように修正することで正常に動くようになった
    • 「3.新規登録画面html」のth:object="${newForm}"th:object="${sampleForm}"に修正
    • 「2.Controllerクラス」のnewFormsampleFormに修正
  • ★別解
    • 「3.新規登録画面html」のエラーメッセージを出す部分を、以下の通り「sampleFormというオブジェクトからとる」「sampleForm」がない時は表示しない、となる変更をす
      <div th:if="${sampleForm}" th:errors="${sampleForm.name}"></div>
    • 「2.Controllerクラス」新規登録処理のif内に、model.addAttribute("newForm", newForm);を追加

事象整理

  • th.errorsの値は、${バリデート設定しているFormクラスの名前(キャメルケース).フィールド名}にする必要がある。
  • 別解の「2.Controllerクラス」のみを対応すると、例外は出ないがエラーメッセージも出ない状態になった
  • 「★別解」のときに、th:if="${sampleForm}"を入れないと、新規登録画面表示時に例外が発生する。(修正前の登録押下時の例外と同じ種類で、sampleFormでダメなようなエラー)
  • 「★別解」で「2.Controllerクラス」のほうの修正がないと、修正前と同じエラーが同じタイミングで発生する

考察

  • バリデーションエラーにかかるとき、BindingResultか何かで
    model.addAttribute("{Formクラスの名前(キャメルケース)}", {入力情報やバリデートエラーメッセージ});
    的なのが自動で設定されているのではないか?と思った
  • 画面表示時に渡しているmodel.addAttributeの属性名が「Formクラス名(キャメルケース)」と等しければ、登録処理から帰って来る時と同じ属性名になるので、入力値が保持されるしエラーメッセージもちゃんと出る

追記:コメントから

下記コメントで原因を理解しました。

  • リクエストパラメータの引数の前に@ModellAttribute("任意の属性名")をつけると、そのリクエストパラメータに対してモデル属性名を付けられる
  • エラーが起きていた時のように、このアノテーションをつけなければルールに沿って自動で命名されていた

原因

この場合のエラーの直接の原因はcreateUserの引数に「newForm」という名前で指定された@ModelAttributeが存在しないことです。

解決法

@ModellAttributeはリクエストのパラメーターと引数のオブジェクトの変換を指定します。

失敗していた時に起きていたこと

@ModelAttributeを指定されていないとき、Springが規約に従って暗黙的に変換していた

2
0
3

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
2
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?