Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 662
kinderproc Avatar asked Jan 18 '26 15:01

kinderproc


1 Answers

You just need to add a new method to with MethodNotAllowedException in its signature.

@ExceptionHandler(value = MethodNotAllowedException.class)
public ResponseEntity<Object> handleMethodNotAllowedExceptionException(MethodNotAllowedException ex) {
    return buildResponseEntity(HttpStatus.METHOD_NOT_ALLOWED, null, null, ex.getMessage(), null);
}

private ResponseEntity<Object> buildResponseEntity(HttpStatus status, HttpHeaders headers, Integer internalCode, String message, List<Object> errors) {
    ResponseBase response = new ResponseBase() //A generic ResponseBase class
            .success(false)
            .message(message)
            .resultCode(internalCode != null ? internalCode : status.value())
            .errors(errors != null
                    ? errors.stream().filter(Objects::nonNull).map(Objects::toString).collect(Collectors.toList())
                    : null);
    
    return new ResponseEntity<>((Object) response, headers, status);
}

You can customize the buildResponseEntityas you please.

UPDATED

I revisited my answer since it didn't meet your requirement. So, it follows like this:

I send post request for a method that accepts GET. This will fire Request method 'POST' not supported as printed below.

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.Looking up handler method for path /v1/user/profile/1 org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported org.springframework.beans.factory.support.DefaultListableBeanFactory.Returning cached instance of singleton bean 'ethGlobalExceptionHandler'

In this case, there is no need to add @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class).

In fact if you do so, the following error will be thrown (since it is already handled),

java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.HttpRequestMethodNotSupportedException]:....

So, the solution will be:

@Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
        HttpHeaders headers, HttpStatus status, WebRequest request) {
    return buildResponseEntity(HttpStatus.METHOD_NOT_ALLOWED, headers, null, ex.getMessage(), Arrays.asList(""));
}
like image 153
Aman Avatar answered Jan 21 '26 06:01

Aman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!