Spring boot 404 error custom error response ReST

59,432

Solution 1

For those Spring Boot 2 users who don't wanna use @EnableWebMvc

application.properties

server.error.whitelabel.enabled=false
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

ControllerAdvice

@RestControllerAdvice
public class ExceptionResolver {

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public HashMap<String, String> handleNoHandlerFound(NoHandlerFoundException e, WebRequest request) {
        HashMap<String, String> response = new HashMap<>();
        response.put("status", "fail");
        response.put("message", e.getLocalizedMessage());
        return response;
    }
}

Source

Solution 2

It is worked for me in case of @RestControllerAdvice with spring boot

spring.mvc.throw-exception-if-no-handler-found=true
server.error.whitelabel.enabled=false
spring.resources.add-mappings=false

@RestControllerAdvice
public class ErrorHandlerController {

@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(value = HttpStatus.NOT_FOUND )
public String handleNotFoundError(NoHandlerFoundException ex) {
    return "path does not exists";
}
}

Solution 3

I've provided the sample solution on how to override response for 404 case. The solution is pretty much simple and I am posting sample code but you can find more details on the original thread: Spring Boot Rest - How to configure 404 - resource not found

First: define Controller that will process error cases and override response:

@ControllerAdvice
public class ExceptionHandlerController {

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(value= HttpStatus.NOT_FOUND)
    @ResponseBody
    public ErrorResponse requestHandlingNoHandlerFound() {
        return new ErrorResponse("custom_404", "message for 404 error code");
    }
}

Second: you need to tell Spring to throw exception in case of 404 (could not resolve handler):

@SpringBootApplication
@EnableWebMvc
public class Application {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);

        DispatcherServlet dispatcherServlet = (DispatcherServlet)ctx.getBean("dispatcherServlet");
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
    }
}

Solution 4

Summing up all answers and comment, I think the best way to do this is-

First, tell spring boot to throw exception in case of no handler found in application.properties

spring.mvc.throw-exception-if-no-handler-found=true

Then handle NoHandlerFoundException in your application. I handle this by following way

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(NoHandlerFoundException.class)
    public void handleNotFoundError(HttpServletResponse response, NoHandlerFoundException ex) {
        ErrorDto errorDto = Errors.URL_NOT_FOUND.getErrorDto();
        logger.error("URL not found exception: " + ex.getRequestURL());
        prepareErrorResponse(response, HttpStatus.NOT_FOUND, errorDto);
    }
}

If you are using Swagger then you can view my other answer to exclude swagger URL from this exception handler

Solution 5

404 error is handled by DispatcherServlet. there is a property throwExceptionIfNoHandlerFound, which you can override.

In Application class you can create a new bean:

@Bean
DispatcherServlet dispatcherServlet () {
    DispatcherServlet ds = new DispatcherServlet();
    ds.setThrowExceptionIfNoHandlerFound(true);
    return ds;
}

...and then catch the NoHandlerFoundException exception in

@EnableWebMvc
@ControllerAdvice
public class GlobalControllerExceptionHandler {
    @ExceptionHandler
    @ResponseStatus(value=HttpStatus.NOT_FOUND)
    @ResponseBody
    public ErrorMessageResponse requestHandlingNoHandlerFound(final NoHandlerFoundException ex) {
        doSomething(LOG.debug("text to log"));
    }
}
Share:
59,432

Related videos on Youtube

Markus
Author by

Markus

Updated on March 08, 2022

Comments

  • Markus
    Markus about 2 years

    I'm using Spring boot for hosting a REST API. Instead of having the standard error response I would like to always send a JSON response even if a browser is accessing the URL and as well a custom data structure.

    I can do this with @ControllerAdvice and @ExceptionHandler for custom exceptions. But I can't find any good ways of doing this for standard and handled errors like 404 and 401.

    Are there any good patterns of how to do this?

    • Opal
      Opal almost 9 years
      Markus, does my answer solve the problem? If so, please accept it.
  • Markus
    Markus almost 9 years
    True, but in this case I'm interested in the 401 and 404 cases in order to be able to have one common error response for all errors to the clients. I don't want to have different structures of error response and as well never respond with anything other than for example JSON.
  • Markus
    Markus almost 9 years
    Yes, but in this case a html error is not suitable due to only rest clients are used.
  • Opal
    Opal almost 9 years
    The structure I presented is the default JSON error response structure. If you need only 401 or 404 just add appropriate exceptions instead of MethodArgumentNotValidException and change the method body.
  • zbstof
    zbstof almost 7 years
    Or use spring.mvc.throw-exception-if-no-handler-found=true property instead of a custom DispatcherServlet bean
  • Reema
    Reema over 6 years
    Is there any way to do this without using the annotation @EnableWebMvc I dont want to enable Web MVC
  • Reema
    Reema over 6 years
    Is there any way to do this without using the annotation @EnableWebMvc I dont want to enable Web MVC
  • Ace Eusebio
    Ace Eusebio about 6 years
    Hi @Reema! Were you able to do it without @EnableWebMvc? I would want to do it without it as well.
  • Reema
    Reema about 6 years
    No, I haven’t got any solution for this yet!
  • Steve
    Steve almost 5 years
    Doesn't work. java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.servlet.NoHandlerFoundException]
  • ptrckdev
    ptrckdev about 4 years
    What are reason to not use @EnableWebMvc ?
  • fightlight
    fightlight about 4 years
    @ptrckdev Adding @EnableWebMvc disables autoconfiguration. See here and here
  • RomanMitasov
    RomanMitasov over 3 years
    spring.resources.add-mappings=false disabled swagger-ui in my service. Is there some workarounds for that?
  • Jonas Pedersen
    Jonas Pedersen about 2 years
    Properties needed in Spring 2.6.x is: spring.mvc.throw-exception-if-no-handler-found=true spring.web.resources.add-mappings=false