In the version of Springboot 3.2.1, following worked:
- class with jakarta.validation.constraints.Size annotation on a field
- Java controller request body with given class annotated with jakarta.validation.Valid;
- Class anotated with ControllerAdvice and @ExceptionHandler(MethodArgumentNotValidException.class) was handling validation exceptions
After spring-boot-starter upgrade to 3.2.2 (and also 3.2.3), MethodArgumentNotValidException is not raised anymore, HandlerMethodValidationException is raised instead.
Comment From: wilkinsona
There were some notable changes in this area in Spring Framework 6.1 (https://github.com/spring-projects/spring-framework/issues/29825). The change that you're seeing may be as a result of a refinement of those changes in a Spring Framework patch release. It's hard to be certain with the level of detail that you've currently provided. You could try using spring.version to override the version of Spring Framework that's used to see if this changes the behavior. If it does, then this will have to be investigated by the Spring Framework team. If it does not then we'll need some more information in the form of a minimal sample that we can use to reproduce the behavior you have described.
Comment From: scottfrederick
This comment on a Spring Framework issue might also be relevant.
Comment From: pepavesely
Hi, @scottfrederick thank you for the link. This issue seems to be duplicate of that one.
@PostMapping("/test1")
ResponseEntity<String> test1(@Valid @RequestBody TestModel testModel) {
return ResponseEntity.ok().build();
}
throws MethodArgumentNotValidException but
@PostMapping("/test2/{param}")
ResponseEntity<String> test2(
@NotNull @PathVariable(name = "param") String param,
@Valid @RequestBody TestModel testModel) {
return ResponseEntity.ok().build();
}
throws HandlerMethodValidationException
My pom.xml is fairly simple:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
<relativePath/>
</parent>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
TestApplication.class:
package com.example.test;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.annotation.HandlerMethodValidationException;
@ControllerAdvice
@RestController
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@PostMapping("/test1")
ResponseEntity<String> test1(@Valid @RequestBody TestModel testModel) {
return ResponseEntity.ok().build();
}
@PostMapping("/test2/{param}")
ResponseEntity<String> test2(
@NotNull @PathVariable(name = "param") String param,
@Valid @RequestBody TestModel testModel) {
return ResponseEntity.ok().build();
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<String> handleException(final MethodArgumentNotValidException ex) {
return ResponseEntity.badRequest().build();
}
@ExceptionHandler
public ResponseEntity<String> handleUncaughtExceptions(final HandlerMethodValidationException ex) {
return ResponseEntity.badRequest().build();
}
@Data
public static class TestModel {
@Size(min = 3)
private String name;
}
}
In spring-boot-starter-parent version 3.2.1, both cases are handled by MethodArgumentNotValidException
Comment From: wilkinsona
Thanks, @pepavesely. Closing as a duplicate of https://github.com/spring-projects/spring-framework/issues/32396.