I am working on an ecommerce backend. I have this CheckoutRestController class with this reserveCartItems(@RequestBody @Valid ReserveItemsRequest reserveItemsRequest) web service. I am sending a request to /api/v1/reserve-items with invalid values for some of the fields. In Postman I see the response status code as 400 Bad Request and response body as:
<!doctype html><html lang="en"><head><title>HTTP Status 400 – Bad Request</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 400 – Bad Request</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).</p><hr class="line" /><h3>Apache Tomcat/9.0.96</h3></body></html>
In pom.xml:
<dependencies><!-- Spring --><!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.9</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.3.9</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-orm --><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>5.3.9</version></dependency><!-- Add Jackson for JSON converters --><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.5</version></dependency><!-- Hibernate --><!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>5.6.0.Final</version></dependency><!-- MySQL --><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.31</version></dependency><!-- C3PO --><!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.5</version></dependency><!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator --><dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>6.2.0.Final</version></dependency><!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor --><dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator-annotation-processor</artifactId><version>6.2.0.Final</version></dependency><!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><!-- https://mvnrepository.com/artifact/redis.clients/jedis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>5.2.0</version></dependency></dependencies>
In CheckoutRestController.java:
@RestController@RequestMapping("/api")public class CheckoutRestController { @Autowired private CheckoutService checkoutService; @PostMapping(path = "/v1/reserve-items", produces="application/json") public ResponseEntity<ReserveItemsResponse> reserveCartItems(@RequestBody @Valid ReserveItemsRequest reserveItemsRequest) { ReserveItemsResponse reserveItemsResponse = checkoutService.reserveCartItems(reserveItemsRequest); if(reserveItemsResponse.getReservationStatus() == ReservationStatus.Failed) { return new ResponseEntity<ReserveItemsResponse>(reserveItemsResponse, HttpStatus.BAD_REQUEST); } return ResponseEntity.ok(reserveItemsResponse); }}
In ReserveItemsRequest.java:
import java.util.List;import javax.validation.Valid;import javax.validation.constraints.NotNull;public class ReserveItemsRequest { @NotNull(message = "User ID must not be null") private Integer userId; @Valid @NotNull(message = "Cart items must not be null") private List<CartItem> cartItems; public ReserveItemsRequest() { } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public List<CartItem> getCartItems() { return cartItems; } public void setCartItems(List<CartItem> cartItems) { this.cartItems = cartItems; } @Override public String toString() { return "ReserveItemsRequest [userId=" + userId +", cartItems=" + cartItems +"]"; }}
In CartItem.java:
import java.math.BigDecimal;import javax.validation.constraints.NotNull;import javax.validation.constraints.Positive;public class CartItem { @NotNull(message = "Product ID must not be null") private Integer productId; @NotNull(message = "Quantity must not be null") @Positive(message = "Quantity must be positive") private Integer quantity; @NotNull(message = "Price per unit must not be null") @Positive(message = "Price must be positive") private BigDecimal pricePerUnit; public Integer getProductId() { return productId; } public void setProductId(Integer productId) { this.productId = productId; } public Integer getQuantity() { return quantity; } public void setQuantity(Integer quantity) { this.quantity = quantity; } public BigDecimal getPricePerUnit() { return pricePerUnit; } public void setPricePerUnit(BigDecimal pricePerUnit) { this.pricePerUnit = pricePerUnit; } @Override public String toString() { return "CartItem [productId=" + productId +", quantity=" + quantity +", pricePerUnit=" + pricePerUnit +"]"; }}
It is certain that the validation is occurring but the MethodArgumentNotValidException is not thrown in console with all details about where the validation failed. And in Postman as well why do I get the repsonse in html format rather than JSON.