前提
登録フォームで入力した値をMyBatis(MySQL)を使って登録する簡易的なアプリ作っています。
TOPページから登録フォーム画面(freeTrialRegist.html)へ遷移する際、エラーが発生しました。
実現したいこと
エラー文から推測するに以下の事例しか考えられないため、MainControllerクラスにてオブジェクトの値の受け渡しを修正しましたが、うまくいきません。th:field="*{name}"でエラーになっています。
- Thymeleafオブジェクトの値を正しく参照できていないまたは、そもそも存在しない
発生している問題・エラーメッセージ
エラーメッセージ Caused by: org.attoparser.ParseException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "/html/freeTrialRegist" - line 39, col 44)
該当のソースコード
【freeTrialRegist.html】
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <!-- このページ固有で読み込むCSS/JS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous"> <!--css--> <link th:href="@{/css/footer.css}" rel="stylesheet"/> <link th:href="@{/css/freeTrialRegist.css}" rel="stylesheet"/> <!-- jQuery --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.css" integrity="sha512-bYPO5jmStZ9WI2602V2zaivdAnbAhtfzmxnEGh9RwtlI00I9s8ulGe4oBa5XxiC6tCITJH/QG70jswBhbLkxPw==" crossorigin="anonymous"/> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js" integrity="sha512-AIOTidJAcHBH2G/oZv9viEGXRqDNmfdPVPYOYKGy3fti0xIplnlgMHUGfuNRzC6FkzIo0iIxgFnr9RikFxK+sw==" crossorigin="anonymous"></script> </head> <body> <!--ヘッダー共通--> <div th:replace="./common/header::header"></div> <!--バリデーション--> <div class="container"> <div th:if="${validationError}" th:each="error : ${validationError}"> <label class="text-danger" th:text="${error}"></label> </div> </div> <!--フォーム--> <div class="col-sm-5"> <form th:action="@{/user/create}" th:object="${trialAddRequest}" th:method="post"> <table class="table table-bordered table-hover"> <!-- お名前 --> <tr> <th class="active col-sm-3">お名前</th> <td> <div class="form-group"> <input type="text" th:field="*{name}" class="form-control"/> </div> </td> </tr> // 以下省略 </form> </div> <!--フッタ共通--> <div th:replace="./common/footer::footer"></div> <!--JQuery--> <script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script> <script type="text/javascript" src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/jquery-datetimepicker@2.5.20/build/jquery.datetimepicker.full.min.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-datetimepicker@2.5.20/jquery.datetimepicker.css"> <script th:src="@{/js/freeTrialRegist.js}" type="text/javascript"></script> </body> </html>
【MainController.java】
package com.example.freetrialdemo.controller; import com.example.freetrialdemo.dto.TrialAddRequest; import com.example.freetrialdemo.service.FreeTrialService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import java.util.ArrayList; import java.util.List; @org.springframework.stereotype.Controller public class MainController { /** * ユーザー情報 Service */ @Autowired private FreeTrialService freeTrialService; // TOP画面表示 @RequestMapping("/html") public String top(Model model) { model.addAttribute("header", "無料体験コース予約"); return "/html/top"; } // 無料体験登録画面の遷移 @GetMapping(value = "/html/freeTrialRegist") public String freeTrialRegist(Model model, TrialAddRequest trialAddRequest) { model.addAttribute("header", "無料体験登録画面" ); // model.addAttribute("trialAddRequest", new TrialAddRequest()); return "/html/freeTrialRegist"; } // 戻るボタンの遷移 @GetMapping(value = "/html/top") public String back(Model model) { model.addAttribute("header", "無料体験コース予約"); return "/top"; } // 登録ボタンの処理 @RequestMapping(value ="/user/create", method = RequestMethod.POST) public String create(@Validated @ModelAttribute TrialAddRequest trialRequest, BindingResult result, Model model) { // バリデーション if (result.hasErrors()) { // 入力チェックエラーの場合 List<String> errorList = new ArrayList<>(); for (ObjectError error : result.getAllErrors()) { errorList.add(error.getDefaultMessage()); } model.addAttribute("validationError", errorList); return "/html/freeTrialRegist"; } // ユーザー登録の処理 freeTrialService.save(trialRequest); model.addAttribute("header", "無料体験登録完了画面"); return "redirect:/html/freeTrialRegistResult"; } }
【TrialAddRequest.java】(DTO)
package com.example.freetrialdemo.dto; import lombok.Data; import javax.validation.constraints.Email; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import java.io.Serializable; @Data public class TrialAddRequest implements Serializable { /** * 名前 */ @NotEmpty(message = "名前を入力してください") @Size(max = 100, message = "名前は100桁以内で入力してください") private String name; /** * 性別 */ @NotEmpty private String sex; /** * 年齢 */ @NotEmpty private String age; /** * メールアドレス */ @NotEmpty(message = "メールアドレスを入力してください") @Email(message = "メールアドレスの形式で入力してください") private String mail; /** * 電話番号 */ @Pattern(regexp = "0\\d{1,4}-\\d{1,4}-\\d{4}", message = "電話番号の形式で入力してください") private String phone; /** * プラン */ @NotEmpty private String plan; /** * 店舗 */ @NotEmpty private String shop; /** * 日付 */ @NotEmpty private String date; }
【FreeTrialMapper.java】(Dao)
package com.example.freetrialdemo.dao; import com.example.freetrialdemo.dto.TrialAddRequest; import org.apache.ibatis.annotations.Mapper; @Mapper public interface FreeTrialMapper { void save(TrialAddRequest trialRequest); }
【freeTrialRegist.java】(Entity)
package com.example.freetrialdemo.entity; import lombok.Data; import lombok.NonNull; import java.io.Serializable; import java.util.Date; @Data public class freeTrialRegist implements Serializable { // id private Long id; // お名前 @NonNull private String name; // 性別 private String sex; // 年齢 private Integer age; // メールアドレス @NonNull private String mail; // 電話番号 @NonNull private String phone; // プラン private String plan; // 店舗 private String shop; // 日付 private Date date; // 最終更新日時 private Date created; }
【FreeTrialService.java】(Service)
package com.example.freetrialdemo.service; import com.example.freetrialdemo.dao.FreeTrialMapper; import com.example.freetrialdemo.dto.TrialAddRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class FreeTrialService { @Autowired private FreeTrialMapper freeTrialMapper; // ユーザー登録 public void save(TrialAddRequest trialAddRequest) { freeTrialMapper.save(trialAddRequest); } }
試したこと
MainControllerの無料体験登録画面へボタン押下時にエラーが発生していることから、「 無料体験登録画面の遷移時」にて以下2パターン試しました。
- TrialAddRequest trialAddRequestを引数で渡す
- コメントアウトになっているmodel.addAttributeでtrialAddRequestをnewする
補足情報(FW/ツールのバージョンなど)
intelliJ 2022.2
Java 8
Spring Initializr 2.7.4
Gradle 7.02
openJDK 16.0.1
あなたの回答
tips
プレビュー