Mam sklep w którym chce dodać nowy produkt, kontroler wygląda w ten sposób :
@RequestMapping("/product/new")
public String newProduct(Model model) {
model.addAttribute("cat", categoryService.getAllCategories());
model.addAttribute("productf", new ProductCommand());
return "product/addProduct";
}
@PostMapping("product")
public String saveNewProduct(@ModelAttribute("productf") ProductCommand productCommand, Model model) {
productService.saveCommand(productCommand);
return "redirect:/index";
}
Formularz:
object="${productf}" th:action="@{/product/}" method="post">
<input type="hidden" th:field="*{id}"/>
<div class="container" style="margin-top: 20px">
<div class="form-group">
<div class="col-md-5">
<h2>Nowy produkt</h2>
<label>Nazwa:</label>
<input type="text" class="form-control" placeholder="Wpisz nazwę produktu" th:field="*{name}"/>
<label>Producent:</label>
<input type="text" class="form-control" placeholder="Wpisz nazwę producenta" th:field="*{manufacturer}"/>
</div>
<div class="col-md-3">
<label>Cena:</label>
<input type="text" class="form-control" placeholder="Wpisz cenę" th:field="*{price}"/>
<label>Liczba produktów:</label>
<input type="text" class="form-control" placeholder="Wpisz l. produktów" th:field="*{unitsInStock}"/>
<label>Wycofany:</label>
<select class="form-control" th:field="*{discontinued}">
<option th:value="true">Tak</option>
<option th:value="false">Nie</option>
</select>
</div>
<div class="col-md-3 form-group">
<label>Kategoria:</label>
</div>
<div class="col-md-9 form-group">
<tr th:each="category : ${cat}">
<div class="radio">
<label>
<input type="checkbox" value="" th:value="${category.id}" th:text="${category.categoryName}" th:field="*{categories}"/>
</label>
</div>
</div>
<div class="col-md-12 form-group">
<label>Opis produktu:</label>
<textarea class="form-control" rows="3" placeholder="Wpisz opis produktu" th:field="*{description}"></textarea>
</div>
<div class="col-md-5">
<button type="submit" class="btn btn-primary bg-info">Submit</button>
</div>
Product i ProductCommand:
@Entity
@EqualsAndHashCode(exclude = "categories")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
private BigDecimal price;
private String manufacturer;
private Long unitsInStock;
private boolean discontinued;
private Byte[] image;
//@ElementCollection
//private Map<String, String> productProperties = new HashMap<>();
@ManyToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "product_category",
joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "category_id"))
private Set<Category> categories = new HashSet<>();
}
@NoArgsConstructor
public class ProductCommand {
private Long id;
private String name;
private String description;
private BigDecimal price;
private String manufacturer;
private Long unitsInStock;
private boolean discontinued;
private Byte[] image;
private Set<CategoryCommand> categories = new HashSet<>();
}
I dostaję taki dziwny error po kliknięciu przycisku wyślij:
Resolved exception caused by Handler execution: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'productf' on field 'categories': rejected value [1]; codes [typeMismatch.productf.categories,typeMismatch.categories,typeMismatch.java.util.Set,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [productf.categories,categories]; arguments []; default message [categories]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Set' for property 'categories'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'info.mike.webstorev1.commands.CategoryCommand' for property 'categories[0]': no matching editors or conversion strategy found]
Co dziwne, gdy metodę kontrolera POST ustawię na:
@PostMapping("product")
public String saveNewProduct(@ModelAttribute("productf") Product product, Model model) {
productService.saveProduct(product);
return "redirect:/index";
}
przy niezmienionej pierwszej metodzie to wszystko działa. Proszę o jakieś wskazówki, bo ja jestem w lesie, obiekty Product i ProductCommand z założenia są identyczne, więc nie mam absolutnie pojęcia, co oznacza ten error i dlaczego przy jednym z nich działa, a przy drugim jest jakiś kłopot z konwersją.