springエラーチェックを実装しています。
初期値が表示される商品更新画面で、入力値が未入力の場合に
未入力の文字を表示させます。
そこで、下記のエラーがでました。
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'ItemForm' available as request attribute
調べると、 th:object="${ItemForm}"の値が使えていないなど考えらるみたいですが
formクラスのオブジェクトを使うのであっていると思うのですが
又、Exception evaluating SpringEL expression: "#fields.hasErrors('name')" と下記のHTML側で問題があるようで
調べています。
他に対処法として考えるべき点があれば教えていただきたいです。
初心者の為、いつもどうしようもない質問すみません。
1. ItemForm フォームクラス
package jp.co.sss.shop.form; import javax.validation.constraints.Digits; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.NotEmpty; import org.springframework.web.multipart.MultipartFile; public class ItemForm { private String id; @NotEmpty @Size(min = 1, max = 100) private String name; @NotEmpty @Digits(integer = 7, fraction = 0) private String price; @NotEmpty @Size(min = 1, max = 400) private String description; @NotEmpty @Digits(integer = 4, fraction = 0) private String stock; private MultipartFile imageFile; private String image; private String categoryId; private String categoryName; private Integer count; public Integer getCount() { return count; } public void setCount(Integer count) { this.count = count; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; }
2.ItemUpdateAdminControllerコントローラー
package jp.co.sss.shop.controller.item; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.multipart.MultipartFile; import jp.co.sss.shop.bean.ItemBean; import jp.co.sss.shop.entity.Category; import jp.co.sss.shop.entity.Item; import jp.co.sss.shop.form.ItemForm; import jp.co.sss.shop.repository.CategoryRepository; import jp.co.sss.shop.repository.ItemRepository; import jp.co.sss.shop.util.BeanCopy; import jp.co.sss.shop.util.Constant; @Controller public class ItemUpdateAdminController { @Autowired ItemRepository itemRepository; @Autowired CategoryRepository categoryRepository; @RequestMapping(path = "/item/update/input", method = RequestMethod.POST) public String updateInput(@ModelAttribute Integer id, Model model) { Item item = itemRepository.findOne(id); ItemBean itemBean = BeanCopy.copyEntityToBean(item); model.addAttribute("item", itemBean); return "item/update/item_update_input"; } @RequestMapping(path = "/item/update/check", method = RequestMethod.POST) public String updateCheck(@Valid @ModelAttribute ItemForm form,BindingResult result,Model model) { if(result.hasErrors()){ return back(model,form); } if (form.getImageFile().getSize() > 0) { MultipartFile file = form.getImageFile(); // アップロード対象のファイル名を取得 String imageName = file.getOriginalFilename(); // 現在の日時を「yyyyMMddhhmmss」形式の文字列として取得 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss"); String date = dateFormat.format(new Date()); // ファイルのアップロード先を指定 imageName = date + "_" + imageName; File uploadPath = new File(Constant.FILE_UPLOAD_PATH, imageName); try { // 指定されたファイルを一時的にアップロード file.transferTo(uploadPath); } catch (Exception e) { e.printStackTrace(); return "error"; } // 一時的にアップロードしたファイルの名前をFormクラスにセット form.setImage(imageName); } else { // 商品画像が未入力の場合、登録済みの画像ファイルを取得する Item item = itemRepository.findOne(Integer.parseInt(form.getId())); form.setImage(item.getImage()); } // 選択したカテゴリの名前をFormクラスにセット Category category = categoryRepository.findOne(Integer.parseInt(form.getCategoryId())); form.setCategoryName(category.getName()); return "item/update/item_update_check"; } @RequestMapping(path = "/item/update/complete", method = RequestMethod.POST) public String updateComplete(@ModelAttribute ItemForm form) { // Formクラス内の各フィールドの値をエンティティにコピー Item item = BeanCopy.copyFormToEntity(form); item.setDeleteFlag(Constant.NOT_DELETED); itemRepository.save(item); return "item/update/item_update_complete"; } @RequestMapping(path = "/item/update/input/back", method = RequestMethod.POST) public String back(Model model, @ModelAttribute ItemForm form) { // ItemFormクラスの各フィールドの値をItemBeanクラスにコピー ItemBean itemBean = BeanCopy.copyFormToBean(form); model.addAttribute("item", itemBean); return "item/update/item_update_input"; } }
3.item_update_check.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="common/layout_4block"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> </head> <body> <th:block layout:fragment="layout-main"> <div class="title">商品更新入力画面</div> <div class="container"> <p>更新する商品を入力してください。</p> <form th:action="@{/item/update/check}" enctype="multipart/form-data" method="post" th:object="${ItemForm}"> <div class="text">商品名</div> <div> <input type="text" name="name" th:value="${item.name}" /> <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span> </div> <div class="text">価格</div> <div> <input type="text" name="price" th:value="${item.price}" /> <span th:if="${#fields.hasErrors('price')}" th:errors="*{price}"></span> </div> <div class="text">説明文</div> <div> <textarea name="description" rows="6" th:field="${item.description}"></textarea> <span th:if="${#fields.hasErrors('description')}" th:errors="*{description}"></span> </div> <div class="text">カテゴリ</div> <div> <select name="categoryId"> <option th:each="category: ${session.categories}" th:value="${category.id}" th:selected="${category.id == item.categoryId}" th:text="${category.name}"></option> </select> </div> <div class="text">在庫数</div> <div> <input type="text" name="stock" th:value="${item.stock}" /> <span th:if="${#fields.hasErrors('stock')}" th:errors="*{stock}"></span> </div> <div class="text">商品画像</div> <div> <div class="value"> <span th:if="${item.image != null}"> <img th:src="@{/img/{image}(image=${item.image})}"></img> </span> <span th:if="${item.image == null}"> <img th:src="@{/img/common/no_image.png}"></img> </span> </div> <div> <input type="file" name="imageFile" /> </div> </div> <input type="hidden" name="id" th:value="${item.id}" /> <input type="submit" value="送信" /> </form> <form th:action="@{/item/list/admin}"> <input type="submit" value="戻る" /> </form> </div> </th:block> </body> </html>