前提・実現したいこと
個人制作ですが、SpringMVC,thymeleaf,JDBCTemplateを使って、基本的なCRUD機能をもつアプリを作りました。
そのアプリの情報入力画面でドロップダウンの選択肢を選ばせる項目があるのですが、そのドロップダウンがデフォルトで「選択してください」という文字列を表示しています。
ドロップダウンの選択肢が選ばれた場合はobj.id(Integer)がvalueに入り問題ないのですが、
デフォルトの文字列が選択された場合は、Stringが取得された扱いになり
typeMismatchを発生させてしまいます(エラーその1)。
今回やりたいことは、このtypeMismatchが発生したときにエラーメッセージを表示し
もう一回入力をやり直させることです。
ちなみに、通常の選択肢はベータベースのテーブルから引っ張ってきてth:eachの形で表示しています。
発生している問題・エラーメッセージ
エラーその1
Field error in object 'stuffForm' on field 'stuffId': rejected value [選択してください]; codes [typeMismatch.stuffForm.stuffId,typeMismatch.stuffId,typeMismatch.int,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [stuffForm.stuffId,stuffId]; arguments []; default message [stuffId]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'stuffId'; nested exception is java.lang.NumberFormatException: For input string: "選択してください"]]
エラーその2
This application has no explicit mapping for /error, so you are seeing this as a fallback. Mon Jul 26 13:58:14 JST 2021 There was an unexpected error (type=Internal Server Error, status=500). An error happened during template parsing (template: "class path resource [templates/DailyReportForm.html]") org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/DailyReportForm.html]") at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241) at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100) (中略) Caused by: org.attoparser.ParseException: Could not parse as expression: "${#fields.hasErrors('stuffId')" (template: "DailyReportForm" - line 69, col 12) at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393) at org.attoparser.MarkupParser.parse(MarkupParser.java:257) at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230) ... 48 more Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "${#fields.hasErrors('stuffId')" (template: "DailyReportForm" - line 69, col 12)
該当のソースコード
HTML
1<!doctype html> 2<html xmlns:th="http://www.thymeleaf.org" 3 xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> 4(中略) 5<main role="main" class="container"> 6<div class="starter-template text-center py-5 px-3"> 7 <form method ="POST" th:action ="${dailyReportForm.newReport}? @{/main/report/insert}:@{/main/report/update}" th:object="${dailyReportForm}"> 8 <p th:if="${complete}" th:text="${complete}" class ="alert alert-primary" role ="alert"></p> 9 <p th:if="${output}" th:text="${output}" class="alert alert-primary" role="alert"></p> 10 <h1 th:text="${title}">Bootstrap スターターテンプレート</h1> 11 12 <div class="form-group"> 13 <label for="exampleFormControlSelect1">スタッフID</label> 14 <!-- 追加記述部分 <div th:if="${#fields.hasErrors('stuffId')" th:errors="*{stuffId}" class="alert alert-danger" role="alert"}></div>--> 15 <select class="form-select form-select-lg mb-3" aria-label=".form-select-lg example" name ="stuffId"> 16 <option>選択してください</option> 17 <option th:each ="obj:${stuff}" th:value ="${obj.id}"th:text ="${obj.registeredId}" ></option> 18 </select> 19 </div> 20 21 <div class="form-group"> 22 <label for="exampleFormControlSelect1">作業区分ID</label> 23 <!-- 追加記述部分 <div th:if="${#fields.hasErrors('workId')" th:errors="*{workId}" class="alert alert-danger" role="alert"}></div>--> 24 <select class="form-select form-select-lg mb-3" aria-label=".form-select-lg example" name="workId"> 25 <option>選択してください</option> 26 <option th:each ="obj:${work}" th:value ="${obj.id}"th:text ="${obj.workDivId}"></option> 27 </select> 28 </div> 29 (中略) 30 <div class="d-grid gap-2"> 31 <input th:if ="${dailyReportId}" type ="hidden" th:value ="${dailyReportId}" name ="dailyReportId"> 32 <button type="submit" class ="btn btn-primary">登録</button> 33 </div> 34 </body> 35</html> 36
ValidationMassages_ja.properties
#typeMismatch typeMismatch.java.lang.Integer ="{0}" must be an integer. #field name stuffId =stuffId workId = workId
Controllerクラス
package com.example.demo.app.dailyreport; import java.io.FileOutputStream; import java.io.IOException; (中略) @Controller @RequestMapping("/main") public class DailyReportController { private final DailyReportService dailyReportService; private int id; private String stuff; private String work; private String progress; private String date; private String start; private String end; private String detail; public DailyReportController(DailyReportService dailyReportService) { this.dailyReportService = dailyReportService; } @GetMapping public String top(Model model) { model.addAttribute("title","日報アプリ"); return"top"; } @GetMapping("/report") public String DailyReport(DailyReportForm dailyReportForm,Model model) { dailyReportForm.setNewReport(true); List<DailyReport> list = dailyReportService.findAll(); List<Stuff> stuff = dailyReportService.findStuff(); List<Work> work = dailyReportService.findWork(); model.addAttribute("list",list); model.addAttribute("stuff",stuff); model.addAttribute("work",work); model.addAttribute("title","日報入力"); return "DailyReportForm"; } (中略) @PostMapping("/report/insert") public String insert( @Valid@ModelAttribute DailyReportForm dailyReportForm, BindingResult result, StuffForm stuffForm, WorkForm workForm, Model model) { DailyReport dailyReport = makeDailyReport(dailyReportForm,0); if(!result.hasErrors()) { dailyReportService.insert(dailyReport); return "redirect:/main/report"; }else { dailyReportForm.setNewReport(true); model.addAttribute("DailyReportForm",dailyReportForm); List<DailyReport> list = dailyReportService.findAll(); List<Stuff> stuff = dailyReportService.findStuff(); List<Work> work = dailyReportService.findWork(); model.addAttribute("stuff",stuff); model.addAttribute("work",work); model.addAttribute("list",list); model.addAttribute("title","日報入力"); return"DailyReportForm"; } (中略) }
試したこと
・resourcesファイル直下にValidationMassages_ja.propertiesファイルを作成し、
htmlにth:if="${#fields.hasError('フィールド名')}から始まる一連のコードを記述しました。
しかし、この記述を入れるとエラーその2が発生し機能しません。
単純なテキスト入力項目で同じコードを記述したときは正常に機能しました。
ドロップダウンとの違いはどこにあるのでしょうか?
・フォームクラスでアノテーションで解決できないかと調べましたが、
typemismatchを直接弾くようなアノテーションはなかったと記憶しています。
以下参考にしたサイトですが、このようなエラーは初めて対処するということもあり
情報が整理しきれない部分がありますがご教示いただけると幸いです。
参考にしたサイト
https://snowsaber.dip.jp/page/spring/validation.html
https://terasolunaorg.github.io/guideline/public_review/ArchitectureInDetail/Validation.html#jsr-303
https://qiita.com/suema0331/items/9b138e5aa2b46009694e
補足情報(FW/ツールのバージョンなど)
STS-4.10.0.RELEASE
java11
ここにより詳細な情報を記載してください。
回答1件
あなたの回答
tips
プレビュー