Search code examples
javaresthttp-status-code-405

How to catch HTTP 405 "Method Not Allowed" exception using @ExceptionHandler?


I created a REST application and added a class to handle exceptions:

@RestControllerAdvice(basePackages = "com.foxminded.university.api.controller")
public class ApiGlobalExceptionHandler extends ResponseEntityExceptionHandler {
    private static final String API_UNHANDLED_EXCEPTION = "REST API reached unhandled exception: %s";
    private static final HttpStatus internalServerError = HttpStatus.INTERNAL_SERVER_ERROR;

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handle(Exception e) {
        ExceptionDetail exceptionDetail = new ExceptionDetail(
            String.format(API_UNHANDLED_EXCEPTION, e.getMessage()),
            internalServerError,
            ZonedDateTime.now(ZoneId.systemDefault()));
        return new ResponseEntity<Object>(exceptionDetail, internalServerError);
    }

    @Override
    public ResponseEntity<Object> handleTypeMismatch(
        TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ExceptionDetail exceptionDetail = new ExceptionDetail(
            String.format(API_UNHANDLED_EXCEPTION, ex.getMessage()),
            internalServerError,
            ZonedDateTime.now(ZoneId.systemDefault()));
        return new ResponseEntity<Object>(exceptionDetail, internalServerError);
    }

    @Override
    public ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException e, HttpHeaders headers,
        HttpStatus status, WebRequest request) {
        ExceptionDetail exceptionDetail = new ExceptionDetail(
            String.format(API_UNHANDLED_EXCEPTION, e.getMessage()),
            internalServerError,
            ZonedDateTime.now(ZoneId.systemDefault()),
            e.getBindingResult().getFieldErrors());
        return new ResponseEntity<Object>(exceptionDetail, internalServerError);
    }
}

When I send the wrong post request via postman http://localhost:8080/api/groups/jkjk instead of http://localhost:8080/api/groups

It throws me an exception that I can't catch initializing when debugging, neither in the ApiGlobalExceptionHandler class nor in the ResponseEntityExceptionHandler class:

{
    "timestamp": 1604171144423,
    "status": 405,
    "error": "Method Not Allowed",
    "message": "",
    "path": "/api/groups/jkjk"
}

All other exceptions I can catch. How do I catch this exception to add custom handling?


Solution

  • I found the explanation here Custom handling for 405 error with Spring Web MVC

    It says The reason your @ExceptionHandler annotated method never catches your exception is because these ExceptionHandler annotated methods are invoked after a successful Spring controller handler mapping is found. However, your exception is raised before that.

    And the solution is to extends not from ResponseEntityExceptionHandler class, but from DefaultHandlerExceptionResolver and override it handleHttpRequestMethodNotSupported method.