Reputation: 53
I have a problem: my post form working fine and the controller related to the post method does receive objects from HTML post form but @Valid
annotation does nothing.
In BindingResult
object there is no error even though it should be there
The problem is in : itemAddControllerPost()
package orchowski.tomasz.ecommercedemo.controller.item;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import orchowski.tomasz.ecommercedemo.command.ItemCommand;
import orchowski.tomasz.ecommercedemo.converter.ItemCommandToItem;
import orchowski.tomasz.ecommercedemo.converter.ItemToItemCommand;
import orchowski.tomasz.ecommercedemo.domain.Item;
import orchowski.tomasz.ecommercedemo.security.permision.PermissionStoreItemCreate;
import orchowski.tomasz.ecommercedemo.security.permision.PermissionStoreItemRead;
import orchowski.tomasz.ecommercedemo.services.ItemService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
import java.util.List;
import java.util.Optional;
@Slf4j
@Controller
@RequestMapping("/item")
@RequiredArgsConstructor
public class ItemController {
private final ItemService itemService;
private final ItemCommandToItem commandToItem;
private final ItemToItemCommand itemToCommand;
@PermissionStoreItemCreate
@GetMapping("/create")
public String itemAddController(Model model) {
model.addAttribute("item", new ItemCommand());
return "item/itemform";
}
@PermissionStoreItemCreate
@PostMapping("/create/new")
public String itemAddControllerPost(@ModelAttribute("item") @Valid ItemCommand itemCommand, BindingResult bindingResult) {
log.debug("Posting new item object");
if (bindingResult.hasErrors()) {
bindingResult.getAllErrors().forEach(objectError -> log.error(objectError.toString()));
log.debug("Binding error");
return "redirect:/item/create";
}
Item save = itemService.save(commandToItem.convert(itemCommand));
log.debug("New item object persisted to db \n " + save.toString());
return "redirect:/item/" + save.getId() + "/show";
}
@PermissionStoreItemRead
@GetMapping("/show")
public String itemRead(Model model, HttpServletRequest request, @RequestParam(defaultValue = "0") Integer pageNo,
@RequestParam(defaultValue = "10") Integer pageSize) {
///item/show?pageNo=2&pageSize=20
if (pageNo < 0 || pageSize <= 0) {
return "redirect:/item/show?pageNo=0";
}
model.addAttribute("pageNumber", pageNo);
model.addAttribute("pageSize", pageSize);
List<Item> itemList = itemService.findAll(pageNo, pageSize);
if (itemList.size() == 0) {
return "redirect:/item/show?pageNo=" + (pageNo - 1);
}
model.addAttribute("items", itemList);
System.out.println(itemList);
return "item/show";
}
@GetMapping("/{id}/show")
@PermissionStoreItemRead
public String showItem(Model model,@PathVariable Long id) {
Optional<Item> byId = itemService.findById(id);
model.addAttribute("item", byId.orElseThrow(() -> new RuntimeException("Item id " + id + " not found")));
return "item/showProduct";
}
}
my command object
package orchowski.tomasz.ecommercedemo.command;
import lombok.*;
import javax.validation.constraints.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ItemCommand {
private Long id;
@Size(min = 20, max = 1000,message = "Description must contains at least 20 characters and less than 1000")
@NotBlank
private String description;
@Min(value = 0, message = "Price have to be greater than 0")
@NotNull
private Double price;
@Min(value = 0, message = "Stock have to be at least 0")
@NotNull
private Integer stock;
}
html form
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>store</title>
<link th:rel="stylesheet" th:href="@{/webjars/bootstrap/5.0.1/css/bootstrap.min.css}">
<link th:rel="stylesheet" th:href="@{/css/default.css}">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-12">
<nav th:replace="fragments/navbar :: nav"></nav>
</div>
</div>
<form th:object="${item}" th:action="@{/item/create/new}" method="post">
<div class="row">
<div class="mb-3">
<!--description -->
<label for="description" class="form-label">Description of product</label>
<textarea class="form-control" id="description" name="description"></textarea>
</div>
</div>
<div class="row">
<div class="col-sm-3">
<!--price -->
<label for="price">Price of product</label>
<input type="text" class="form-control" id="price" name="price">
</div>
<div class="col-sm-3">
<!--stock -->
<label for="stock">Stock item</label>
<input type="text" class="form-control" id="stock" name="stock">
</div>
</div>
<div class="row">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
<script th:src="@{/webjars/jquery/3.0.0/jquery.min.js}"></script>
<script th:src="@{/webjars/popper.js/2.9.2/umd/popper.js}"></script>
<script th:src="@{/webjars/bootstrap/5.0.1/js/bootstrap.js}"></script>
</body>
</html>
To check the code on GitHub please click here
Upvotes: 2
Views: 4190
Reputation: 301
Change:
@Valid -> @Validated
import org.springframework.validation.annotation.Validated;
I didn't go into details, but it worked in my case.
Upvotes: 0
Reputation: 53
Problem has been solved!
I change hibernate dependency in pom.xml from
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>7.0.1.Final</version>
</dependency>
to
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
Upvotes: 2
Reputation: 13261
Try:
import javax.validation.Valid;
https://docs.oracle.com/javaee/7/api/javax/validation/Valid.html
Instead of:
import jakarta.validation.Valid;
(an ambiguous import!;)
Useful read: https://www.google.com/search?q=spring+valild
(@javax.validation.Valid
vs. @org.springframework.validation.annotation.Validated
)
Further read:
jakarta.validation.Valid
: ??? (SpringBoot with Jakarta Validation Api not validating with @Valid Annotation, https://www.google.com/search?q=jakarta.validation.Valid (looks obsolete !???)) Check your class path/dependency tree!
Actually I found no/few samples, where the import statements is explicitly mentioned, but it is "clear" that spring supports JSR 303 (i.e. javax.validation.*
and rather not jakarta.validation.*
..)
Upvotes: 1