HOWTO handle 404 exceptions globally using Spring MVC configured using Java based Annotations

17,965

Solution 1

By default, the DispatcherServlet does not throw a NoHandlerFoundException. You need to enable that.

The AbstractAnnotationConfigDispatcherServletInitializer should let you override how the DispatcherServlet is created. Do that and call

DispatcherServlet dispatcherServlet = ...; // might get it from super implementation
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);

Solution 2

Enable DispatcherServlet throw a NoHandlerFoundException through web.xml configuartion.

<init-param>
    <param-name>throwExceptionIfNoHandlerFound</param-name>
    <param-value>true</param-value>
</init-param>

Solution 3

Instead overriding registerDispatcherServlet one can override the createDispatcherServlet method as follows.

@Override
    protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
        DispatcherServlet ds = new DispatcherServlet(servletAppContext);
        ds.setThrowExceptionIfNoHandlerFound(true);
        return ds;
    }

Solution 4

I resolved the problem with the following entry in my application.yml

 server.error.whitelabel.enabled: false
 spring.mvc.throw-exception-if-no-handler-found: true

and the following ControllerExceptionHandler:

@ControllerAdvice
public class ControllerExceptionHandler {

@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String processMethodNotSupportedException(Exception exception) {
    exception.printStackTrace();
    return "error";
}

}

and last but not least i added a template "/html/error.html"

Share:
17,965
Chantz
Author by

Chantz

Updated on June 03, 2022

Comments

  • Chantz
    Chantz almost 2 years

    I am building a Spring 4 MVC app. And it is completely configured using Java Annotations. There is no web.xml. The app is configured by using instance of AbstractAnnotationConfigDispatcherServletInitializer and WebMvcConfigurerAdapter like so,

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = {"com.example.*"})
    @EnableTransactionManagement
    @PropertySource("/WEB-INF/properties/application.properties")
    public class WebAppConfig extends WebMvcConfigurerAdapter {
    ...
    }
    

    and

    public class WebAppInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {
    ...
    }
    

    I am now trying to add a global/catch-all exception handler for 404 pages i.e. HttpStatus.NOT_FOUND but no success. Below are some of the ways I tried.

    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.NoHandlerFoundException;
    import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
    
    @ControllerAdvice
    public class GlobalExceptionHandlerController {
    
        @ExceptionHandler
        @ResponseStatus(HttpStatus.NOT_FOUND)
        public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) {
                ModelAndView mav = new ModelAndView();
                return mav;
        }
    
        @ExceptionHandler
        @ResponseStatus(HttpStatus.NOT_FOUND)
        public ModelAndView handleExceptiond (NoHandlerFoundException ex) {
                ModelAndView mav = new ModelAndView();
                return mav;
        }
    
        @ResponseStatus(HttpStatus.NOT_FOUND)
        @ExceptionHandler(NoHandlerFoundException.class)
        public void handleConflict() {
    
        }
    
        @ResponseStatus(HttpStatus.NOT_FOUND)
        @ExceptionHandler(NoSuchRequestHandlingMethodException.class)
        public void handlesdConflict() {
        }
    
    }
    

    None of these methods get executed. I am at a loss as to how to handle this. I do not want to use web.xml becasue then I would have to create one just for this.

  • Chantz
    Chantz almost 10 years
    Thanks @Sotirios for the response. But I dont seem to be able to get the dispatcherServlet in AbstractAnnotationConfigDispatcherServletInitializer.
  • Sotirios Delimanolis
    Sotirios Delimanolis almost 10 years
    @Chantz Override the registerDispatcherServlet. Look at the implementation of the super type to get an idea of what to do.
  • Link
    Link almost 9 years
    One year later... Is there a simpler way of doing this? I usually don't override registerDispatcherServlet in my Initializer so I find this method too verbose. All those lines rewritten just to add one line.
  • Sotirios Delimanolis
    Sotirios Delimanolis almost 9 years
    @Link Looking at the source, it doesn't look like they've changed it.
  • Ysak
    Ysak over 8 years
    But you can override createDispatcherServlet by adding one more line to it as I mentioned down
  • kyakya
    kyakya about 3 years
    After SpringBoot version 2.0, using spring.mvc.throwExceptionIfNoHandlerFound: true