HOWTO handle 404 exceptions globally using Spring MVC configured using Java based Annotations
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"
Chantz
Updated on June 03, 2022Comments
-
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 ofAbstractAnnotationConfigDispatcherServletInitializer
andWebMvcConfigurerAdapter
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 almost 10 yearsThanks @Sotirios for the response. But I dont seem to be able to get the
dispatcherServlet
inAbstractAnnotationConfigDispatcherServletInitializer
. -
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 almost 9 yearsOne 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 almost 9 years@Link Looking at the source, it doesn't look like they've changed it.
-
Ysak over 8 yearsBut you can override createDispatcherServlet by adding one more line to it as I mentioned down
-
kyakya about 3 yearsAfter SpringBoot version 2.0, using
spring.mvc.throwExceptionIfNoHandlerFound: true