Search code examples
javaspring-bootvalidationexceptionhandler

Can I get all validation errors in spring boot web application?


I have a pojo like below (please assume a controller and rest of the code. Application is in Spring boot):

@Getter  @Setter
@AllArgsConstructor  @NoArgsConstructor
public class User  {
    @NotBlank(message = "userName is blank")
    private String userName;

    @NotBlank(message = "secretKey is blank")
    private String secretKey;
}

and defined a ExceptionHandler class annotated with @ControllerAdvice and defined a method as bellow:

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    protected ResponseEntity<ErrorResponse> handleMethodArgNotValidException(MethodArgumentNotValidException ex,Locale locale) {
        // code to handle exception.
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = {WebExchangeBindException.class})
    protected ResponseEntity<ErrorResponse> handleException(WebExchangeBindException ex, Locale locale) {
        // code to handle exception.
    }

But in this case even if both fields have validation errors client is getting only one.

I want to ask that is there any way I can list out all the validation errors in the response of this endpoint?

curl --location --request POST 'localhost/api/login' \
--header 'Content-Type: application/json' \
--data-raw '{
    "userName": null,
    "secretKey": null
}'


Solution

  • You can get the BindingResult from MethodArgumentNotValidException and then compose a message based on all rejected fields, for example:

    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ExceptionHandler(value = {MethodArgumentNotValidException.class})
        protected ResponseEntity<ErrorResponse> handleMethodArgNotValidException(MethodArgumentNotValidException ex, Locale locale) {
    
            String errorMessage = ex.getBindingResult()
                    .getFieldErrors()
                    .stream()
                    .map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage())
                    .collect(Collectors.joining("; "));
    
            // put errorMessage into ErrorResponse
            // return ResponseEntity<ErrorResponse>
        }
    }
    

    Example of possible output with message:

    {
        "timestamp": "2022-01-28T17:18:53.1738558+03:00",
        "status": 400,
        "error": "BadRequest",
        "errorMessage": "userName: userName is blank; secretKey: secretKey is blank"
    }