404 Exception not handled in Spring ControllerAdvice
Asked Answered
C

3

9

I have a simple Spring MVC application in which I want to handle all the unmapped urls using @ControllerAdvice. Here is the controller:

@ControllerAdvice
public class ExceptionHandlerController {
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public String handle404() {
        return "exceptions/404page";
    }
}

Still, every time get Whitelabel Error Page.

I tried using RuntimeException.class, HttpStatus.BAD_REQUEST and extending the class with NoHandlerFoundException but no use.

Any suggestions?

Cursor answered 9/1, 2019 at 18:28 Comment(0)
U
10

To make it work, you need to set throwExceptionIfNoHandlerFound property on DispecherServlet. You can do that with:

spring.mvc.throwExceptionIfNoHandlerFound=true

in application.properties file, otherwise the requests will always be forwarded to the default servlet and NoHandlerFoundException would ever be thrown.

The problem is, even with this configuration, it doesn't work. From the documentation:

Note that if org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler is used, then requests will always be forwarded to the default servlet and NoHandlerFoundException would never be thrown in that case.

Because Spring Boot uses by default the org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler you'll have to override this using your own WebMvcConfigurer:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        // Do nothing instead of configurer.enable();
    }
} 

Of course, the above class might be more complicated in your case.

Unimproved answered 9/1, 2019 at 20:30 Comment(1)
Using spring boot 2.0.2.RELEASE this solution didn't work. Had to write a ErrorController as in the answer by zwlxtPlaid
C
3

Another way to do so is ErrorController

@Controller
public class MyErrorController implements ErrorController {

    @GetMapping("/error")
    public ModelAndView errorHandler(HttpServletRequest req) {
        // Get status code to determine which view should be returned
        Object statusCode = req.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        // In this case, status code will be shown in a view
        ModelAndView mav = new ModelAndView("error_default");
        mav.addObject("code", statusCode.toString());
        return mav;
    }

    public String getErrorPath() {
        return "/error";
    }
}
Cephalopod answered 26/1, 2019 at 16:23 Comment(0)
D
0

Add the below line in application.properties

spring.mvc.throwExceptionIfNoHandlerFound=true

and @EnableWebMvc with @ControllerAdvice, Note: add @Override over handleNoHandlerFoundException method this worked for me!

@EnableWebMvc
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    @Override
    protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers,
            HttpStatus status, WebRequest request) {
        CustomResponse response = new CustomResponse();
        response.setTimestamp(LocalDateTime.now());
        response.setMessage(ApplicationErrorCodes.NO_HANDLER_FOUND.getErrorMessage());
        response.setStatus(HttpStatus.BAD_REQUEST);
        response.setErrorCode(ApplicationErrorCodes.NO_HANDLER_FOUND.getErrorCode());
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }
}
Dorathydorca answered 14/12, 2022 at 5:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.