Search code examples
springspring-bootbean-validation

Jakarta Validation and Spring Boot - How to get field name in ConstraintViolationException?


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.


Solution

  • 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.