Hi Spring team,

I am extending ResponseEntityExceptionHandler to implement a global exception handler, and I come across these two problems.

  1. Return ResponseEntity statement seems not working without @ResponseStatus for built-in exception types.

For example, I throw an IllegalArgumentException in controller when a param fails validation. Then I catch the exception in GlobalExceptionHandler

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(IllegalArgumentException.class)
    protected ResponseEntity<Result> illegalParamErrorHandler(IllegalArgumentException ex) {
        return new ResponseEntity<>(
                ResultUtil.error(ErrorCodeEnum.ERROR_CODE_BAD_REQUEST, ex.getMessage()),
                HttpStatus.BAD_REQUEST
        );
    }
}

The response code is still 500 Internal Error instead of assigned HttpStatus.BAD_REQUEST as expected.

Then I tried to add @ResponseStatus annotation and it worked. The response code becomes 400.

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)    // <--------- add this line 
    protected ResponseEntity<Result> illegalParamErrorHandler(IllegalArgumentException ex) {
        return new ResponseEntity<>(
                ResultUtil.error(ErrorCodeEnum.ERROR_CODE_BAD_REQUEST, ex.getMessage()),
                HttpStatus.BAD_REQUEST
        );
    }
}

[Question] Just to confirm, I am not sure is this an expected behavior?

  1. Is conditional response status code mapping supported for custom Exception?

For this case, I have a custom Exception class holding some detailed error info:

public class CustomException extends RuntimeException {
    private final CustomFaultInfo faultInfo;
    // getters and setters
}

public class CustomFaultInfo {
    private String code;
    private String message;
    // getters and setters
}

Then I intercept this exception in GlobalExceptionHandler. What I tried to do is to read the detailed error code info in my CustomException object and decide which status code to return. So here comes the code:

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(CustomException.class)
    protected ResponseEntity<Result> CustomErrorHandler(CustomException ex) {
        CustomFaultInfo faultInfo = ex.getCustomFaultInfo();
        if (faultInfo != null) {
            String errorCode = faultInfo.getCode();
            if (errorCode.equals("400")) {
                return new ResponseEntity<Object>(
                        ResultUtil.error(ErrorCodeEnum.ERROR_CODE_BAD_REQUEST, ex.getMessage()),
                                                HttpStatus.BAD_REQUEST
                );
            }
            if (errorCode.equals("404")) {
                return new ResponseEntity<Object>(
                        ResultUtil.error(ErrorCodeEnum.ERROR_CODE_NOT_FOUND, ex.getMessage()),
                                                HttpStatus.NOT_FOUND
                );
            }
        }
    }
}

This code does not work as expected. When faultInfo.getCode() == 400 it returns a status code of 400, which is correct. However when faultInfo.getCode() == 404 it still returns a status code 400 instead of 404.

Unfortunately in this case I cannot use the @ResponseStatus annotation as a workaround either.

[Question] Is there a way to support such scenario?


I did some digging both on Google, SO and source code, yet found few information that helps. Could you please help explain this a bit? Really appreciated.

Best regards, Kevin

Comment From: rstoyanchev

None of this makes sense based on the description alone. The one thing that stands out is extending ResponseEntityExceptionHandler. That shouldn't be necessary for global exception handling.

That said these questions are more suited for StackOverlow. I suggest however you prepare a sample to demonstrate the issues to improve the chance of getting a response.