0

I was able to get the @Valid working and have validation responses return from my API, if a request body is not properly following the request model. However, it only works if I delete my Controller advice. With the AdviceController, I only get a blank BadRequest response. How can I maintain my global AdviceController and still get back the proper validation error messages. Also it would be nice to be able to customize the BadRequest error messages in the controller as well.

Controller:

@PostMapping(value = "/create", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<LinkTokenCreateResponse> createLinkToken(@Valid @RequestBody CreateLinkTokenReq createLinkTokenReq) throws Exception {

I have the required validation dependencies in the Pom:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>2.5.5</version>
        </dependency>

        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>

I have the error messages set to be included in responses in the Application.yaml:

server:
  error:
    include-message: always
    include-binding-errors: always

I have the @Valid annotations in the Controller advice:

@ControllerAdvice
@Slf4j
public class AdviceConfig extends ResponseEntityExceptionHandler {

    @ExceptionHandler(value = {SQLException.class})
    public ResponseStatusException handleSQLException(final SQLException e) {
        return new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage());
    }
}

I tried implementing a custom BadRequest error handler in the AdviceController, but I get an error from Spring:

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, String> handleValidationExceptions(
  MethodArgumentNotValidException ex) {
    Map<String, String> errors = new HashMap<>();
    ex.getBindingResult().getAllErrors().forEach((error) -> {
        String fieldName = ((FieldError) error).getField();
        String errorMessage = error.getDefaultMessage();
        errors.put(fieldName, errorMessage);
    });
    return errors;
}
TrollBearPig
  • 496
  • 1
  • 7
  • 17
  • 1
    Because you extend ResponseEntityExceptionHandler, you should override the correct method which is provided by its self: handleMethodArgumentNotValid, refer to: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.html#handleMethodArgumentNotValid-org.springframework.web.bind.MethodArgumentNotValidException-org.springframework.http.HttpHeaders-org.springframework.http.HttpStatus-org.springframework.web.context.request.WebRequest- – Huy Nguyen Oct 17 '21 at 04:57
  • @huy why should I have to override every method though. I should be able to add the custom error handling I need to my advice controller while still having the original functionality of the normal spring error handling working. – TrollBearPig Oct 18 '21 at 03:21
  • 1
    You don't need to override all methods, just need to override what you need. Actually, with using the ControllerAdvice and ExceptionHandler, you don't need to extend ResponseEntityExceptionHandler . In my project, using ControllerAdvice and ExceptionHandler is enough for me. – Huy Nguyen Oct 18 '21 at 03:24
  • @huy thanks!! Holy cow that worked. I'm surprised all the guides on bealdung advise to extend that class, you'd think it would be a more common problem. But I do see similar mentioned here: [stackoverflow](https://stackoverflow.com/questions/56527952/spring-boot-rest-responding-with-empty-body-for-exceptions-other-than-the-ones-o) – TrollBearPig Oct 18 '21 at 04:04
  • in ResponseEntityExceptionHandler class, it handle all type exceptions, so it's handy ... In case we need to customize specific exception, just need override the corresponding method. – Huy Nguyen Oct 18 '21 at 06:07

0 Answers0