Reputation: 2105
My intention is to define one global custom 404 page for all my controllers and one global 500 page for all the exceptions. I read a bunch of questions here + all the articles from Google first results page.
I have a WebInitializer:
public class MyWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(WebAppConfiguration.class);
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
DispatcherServlet servlet = new DispatcherServlet(dispatcherContext);
servlet.setThrowExceptionIfNoHandlerFound(true);
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", servlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
And now I have following exceptions handler:
@ControllerAdvice
public class CustomGlogalExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = "/error/500";
@ExceptionHandler(value = Exception.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
throw e;
ModelAndView mav = new ModelAndView();
mav.addObject("url", req.getRequestURL());
mav.setViewName(DEFAULT_ERROR_VIEW);
return mav;
}
@ExceptionHandler(value = NoHandlerFoundException.class)
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public ModelAndView noPageFoundHandler(HttpServletRequest req, Exception e) throws Exception {
ModelAndView mav = new ModelAndView();
mav.addObject("url", req.getRequestURL());
mav.setViewName("/error/404");
return mav;
}
}
It works fine on hitting http://localhost:8080/test
: I get my 404 custom page + response code 404.
It also works fine if I throw artificially somewhere: it shows my 500 custom page + response code 500.
But if some real exception happens, I don't get neither 500 response code nor my custom 500 page.
For example now I have org.hibernate.LazyInitializationException
but what I see in Chrome console is just 200 response code though I see full stack trace in server console, and the exception is the last it shows.
Also, if Thymeleaf template engine throws, it shows full stack trace in the browser.
What else should I configure to make it work correctly?
Thanks.
Upvotes: 0
Views: 1027
Reputation: 11017
spring will not pickup your throwable class. [ExceptionHandlerExceptionResolver][1]
expects exception or its subtypes.
so should be
@ExceptionHandler(value = Excepton.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
Hence whatever your annotated get rethrown and handled to 500, rest goes without spring notice
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
throw e;
Or.
Other option is to use SimpleMappingExceptionResolver, by just declaring it
<bean id="simpleMappingExceptionResolver" class=
"org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<map>
<entry key="Exception" value="gen_error"/>
</map>
</property>
<!-- See note below on how this interacts with Spring Boot -->
<property name="defaultErrorView" value="error"/>
<property name="exceptionAttribute" value="ex"/>
<!-- Name of logger to use to log exceptions. Unset by default,
so logging is disabled unless you set a value. -->
<property name="warnLogCategory" value="example.MvcLogger"/>
</bean>
= bean
@Bean
public SimpleMappingExceptionResolver exceptionResolver() {
SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
Properties exceptionMappings = new Properties();
exceptionMappings.put("java.lang.Exception", "error/error");
exceptionMappings.put("java.lang.RuntimeException", "error/error");
exceptionResolver.setExceptionMappings(exceptionMappings);
return exceptionResolver;
}
Upvotes: 1