yuusuke-roughの日記

Java,SpringBoot,趣味等

バリデーションとDate、そしてバインディングできないのによくハマるお話 in Spring Boot

入力値チェックを丸々忘れていたURLがあったので、実装と有耶無耶にしないための再学習を行います。

 

まずは、チュートリアル

入門 | フォーム入力の検証

 

  • フォームに記入された属性を収集するために @Valid でマークされた personForm オブジェクト。

  • bindingResult オブジェクト。検証エラーをテストおよび取得できます。

 

上記を表示するのはこちらですね。

<td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</td>

 

ひとまず、Binding Resultの話まで。

What is the use of BindingResult interface in spring MVC? - Stack Overflow

Binding ResultのgetFieldErrorsにFieldErrorがあり、このFieldErrorのgetDefaultMessageが表示される。このメッセージについては、validation内にmessageを設定する事で変更できます。フィールドごとに設定しなくてはいけないので少し歯がゆいです。messageSourceで管理した方が良い気もしますが、今回は直接設定してしまいます。

 

今回のモデルのフィールドは部屋名、期限、パスワード有無のフラグ、パスワードです。今回、ピックアップしたいのは、期限です。

HTMLのカレンダーから入力する形式ですが、過去の日付も選べます。

以上、設定するバリデーションとしては、①HTMLのカレンダーから選択した時の文字形式か正規表現で確認②過去の日付を選んでいないか、の2点です。

 

CustomValidationについてはこちらを参考にします。

https://www.baeldung.com/spring-mvc-custom-validator

Hibernate Validatorのドキュメントも参考にします。

https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-customconstraints

 

An annotation type is defined using the @interface keyword. All attributes of an annotation type are declared in a method-like manner. The specification of the Jakarta Bean Validation API demands, that any constraint annotation defines:

  • an attribute message that returns the default key for creating error messages in case the constraint is violated

  • an attribute groups that allows the specification of validation groups, to which this constraint belongs (see Chapter 5, Grouping constraints). This must default to an empty array of type Class<?>.

  • an attribute payload that can be used by clients of the Jakarta Bean Validation API to assign custom payload objects to a constraint. This attribute is not used by the API itself. 

@Targetについては、記載が既にありますが、下記もメモ。

https://docs.oracle.com/javase/jp/8/docs/api/java/lang/annotation/ElementType.html

 

payloadとgroupsについては後日。

後は①、②を実装して終わりです。(投げやり)

 

Date型について

Date date1 =dateFormat.parse("2023-03-10"); 

date1.getTime()で1678374000000

 Date date2 = new Date(2023,03,10);

date2.getTime()で61639196400000

後日調べる事とします。

 

一応、フロント側でも入力を制限する事にしました。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/date

 

最小の日付についてはminを使いますが、変数式を使いたいのでth:min。

https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.html

お手軽。ありがとうThymeleaf。

 

最後に、Binding Resultでエラーを表示するためにth:fieldに直すも

Caused by: org.attoparser.ParseException: Error during execution of processor 'org.thymeleaf.spring6.processor.SpringInputGeneralFieldTagProcessor' (template: "discussion/createRoom" - line 13, col 21)

これは、原因も忘れたので後日調べますが、@ModelAttributeでnameを指定していない時に起こります。GetでもPostでも必要です。(Spring Bootに触れ始めたころに苦しめられ、idとnameでform送信していたのを思い出しました。)

 

感想

相変わらずハマる事がありますが、入社してから生産性が上がりました。

しかし、欲を言うとHibernateのドキュメントもじっくり読み込んで理解したかった気持ちもあります。後は残りの機能を追加して単体テストで終了です。