2

I have a problem with Spring's exception handling for controllers. I have a class annotated with @RestControllerAdvice with a couple of @ExceptionHandler's, like this:

@ExceptionHandler(HttpRequestMethodNotSupportedException::class)
fun methodNotSupportedException(
    exception: HttpRequestMethodNotSupportedException,
    request: HttpServletRequest
): ResponseEntity<ApiError> {
    logger().error("Method not supported: {}", exception.message)
    val methodNotAllowed = HttpStatus.METHOD_NOT_ALLOWED
    val apiError = logAndBuildApiError(request, methodNotAllowed, exception)
    return ResponseEntity(apiError, methodNotAllowed)
}

and they work perfectly fine. In this case, when I'm trying to use an non-implemented HTTP method like POST:

{
    "requestUri": "/api/v1/items",
    "status": 405,
    "statusText": "Method Not Allowed",
    "createdAt": "2023-01-12T16:50:36.55422+02:00",
    "errorMessage": "Request method 'POST' not supported"
}

What I would like to achieve is to handle situations when someone is trying to reach an non-existing endpoint, i.e. the correct one is GET http://localhost:8080/api/v1/items.

But when I'm trying to reach http://localhost:8080/api/v1/itemss, which is of course nonexistent, I recieve a regular Spring whitelabel error page, but I would like to receive a JSON like in the former example:

{
    "requestUri": "/api/v1/itemss",
    "status": 404,
    "statusText": "Not Found",
    "createdAt": "2023-01-12T16:52:06.932108+02:00",
    "errorMessage": "Some error message"
}

How do I implement a @ExceptionHandler so it could handle exceptions related to non-existing resources?

7
  • Does this answer your question? Spring Boot and custom 404 error page Commented Jan 12, 2023 at 15:00
  • baeldung.com/spring-boot-custom-error-page Commented Jan 12, 2023 at 15:01
  • Have you tried @ControllerAdvice as this doesn't really match an @RestController but anything. You would also need an exception handler for a NoHandlerFoundException Commented Jan 12, 2023 at 15:12
  • @MuratKaragöz I've seen this question, no, this doesn't help me, sadly. Commented Jan 12, 2023 at 15:19
  • @M.Deinum changing from RestControllerAdvice to ControllerAdvice doesn't help Commented Jan 12, 2023 at 15:20

2 Answers 2

1

spring.mvc.throw-exception-if-no-handler-found works in conjunction with spring.mvc.static-path-pattern. By default, the static path pattern is /**, which includes the whitelabel error pages that you're seeing.

See https://github.com/spring-projects/spring-boot/pull/31660 and https://gitter.im/spring-projects/spring-boot?at=62ba1378568c2c30d30790af and https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#web.servlet.spring-mvc.static-content

Option one is to set these two properties in your configuration.

spring:
  mvc:
    throw-exception-if-no-handler-found: true
    static-path-pattern: /static

Option 2 is to add @EnableWebMvc to your spring boot application, and set the spring.mvc.throw-exception-if-no-handler-found property to true. By adding EnableWebMvc you'll be getting the WebMvcConfigurationSupport bean, which will cause Spring not to initialize the WebMvcAutoConfiguration and thereby not set the static-path-pattern.

Sign up to request clarification or add additional context in comments.

5 Comments

Don't add @EnableWebMvc (it will also render that property useless) but will disable a lot more then only the static resources.
See the comment by @M.Deinum. There are side effects to using @EnableWebMvc that you may encounter. e.g. if you're controllers are annotated with @Controller instead of @RestController, they will not get handlers registered for their mappings.
That isn't a side effect, in fact the @Controller will work just fine. You won't get pre-configured jackson, the jackson you have will not be integrated into other parts of the framework, no exception handling etc. etc.
@M.Deinum Are you certain that Controllers will work just fine? I have a vanilla spring boot api with RestControllers. If I change them to @Controller and add @EnableWebMvc, the handlers are not registered. If I drop @EnableWebMvc and leave @Controller, they work as expected. I agree though, @EnableWebMvc doesn't play nicely with spring boot.
Yes, as an @RestController itself is also an @Controller but just with an added @ResponseBody by default for the return types. If you have an @Controller with @EnableWebMvc you manually need to define the view resolvers etc. without those (and not using @ResponseBody) they won't resolve any views.
1

spring.mvc.throwExceptionIfNoHandlerFound=true is now deprecated

You may handle 404 error by handling NoResourceFoundException.class Exception

    @ResponseStatus(value = HttpStatus.NOT_FOUND)
@ExceptionHandler(value = NoResourceFoundException.class)
public ResponseEntity<Object> handleNotfound(){
    ResponseBean response = new ResponseBean();
    response.setResponseCode(ResponseConstants.ResponseCodes.ERROR_URL.getCode());
    response.setMessage(ResponseConstants.ResponseCodes.ERROR_URL.getMessage());
    return new ResponseEntity<>(response,  HttpStatus.NOT_FOUND);
}

ResponseBean is my custom class

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.