I have the following controller:
@RestController
@RequestMapping("/people")
@Validated
public class PersonController {
@GetMapping
public List<Person> get(@RequestParam @Size(min= 3) String city){
return List.of(new Person("Henrique " + city));
}
}
When the client sends a request with the attribute city that has a size smaller than 3, the controller throws a ConstraintViolationException
.
When this exception is thrown, I want the service to return a body containing the name of the field that has a validation error, in this example, the field is city
. In order to do this, I created the following controller advice:
@ControllerAdvice
public class ConstraintViolationExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Error>
handleConstraintViolationException(ConstraintViolationException ex){
List<ErrorDetail> details =
ex.getConstraintViolations().stream()
.map(e -> new ErrorDetail(e.getPropertyPath().toString(), e.getMessage()))
.toList();
return new ResponseEntity<>(new Error(ex.getMessage(), details), BAD_REQUEST);
}
}
However, the return that I get is the following:
{
"message": "get.arg0: size must be between 3 and 2147483647",
"details": [
{
"field": "get.arg0",
"description": "size must be between 3 and 2147483647"
}
]
}
How can I change the code so it returns the field name city
instead of get.arg0
?
A running example of this is available in https://github.com/henriquels25/spring-boot-validation-sample.
To replace arg0
with city
in the path, you need add the -parameters
flag when compiling. That will include the parameter name in compiled code, which makes it available for reflection.