Spring MVC provides various mechanisms for error handling which are based on HandlerExceptionResolver interface.
Comparing with Servlet based error handling where we do mapping from 'http error code' and 'java exceptions' to servlets or pages, the interface HandlerExceptionResolver deals with 'java exceptions' only, that raised during controller execution. As we can programmatically take actions on exception scenarios, this approach is more flexible than web.xml mapping approach.
The interface HandlerExceptionResolver has only one method as shown in the following snippet:
package org.springframework.web.servlet;
....
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex);
}
The 'handler' parameter contains the Controller's handler method information where exception occurred. This parameter normally is the instance of HandlerMethod in Spring MVC. The method resolveException() will be invoked even if the exception is thrown outside of the target handler method, before or after handler's invocation but still in the course of target handler method invocation, for example in a handler interceptor.
Example
In this example we are not going to use Spring Boot because Boot has additional default functionality regarding error handling. Here we are going to use traditional @EnableWebMvc approach to understand mvc only error handling aspect.
Creating and registering HandlerExceptionResolver implementation as a bean.
@EnableWebMvc
public class Config {
@Bean
HandlerExceptionResolver errorHandler () {
return new HandlerExceptionResolver() {
@Override
public ModelAndView resolveException (HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
ModelAndView model = new ModelAndView("error-page");
model.addObject("exceptionType", ex);
model.addObject("handlerMethod", handler);
return model;
}
};
}
//registering an interceptor
@Bean
public WebMvcConfigurer webMvcConfigurer () {
return new WebMvcConfigurerAdapter() {
@Override
public void addInterceptors (InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptorAdapter() {
@Override
public boolean preHandle (HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
if (request.getParameter("testParam") != null) {
throw new Exception("exception from interceptor");
}
return true;
}
});
}
};
}
@Bean
public ViewResolver viewResolver () {
InternalResourceViewResolver viewResolver =
new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Bean
public ExampleController myMvcController () {
return new ExampleController();
}
}
The Controller
@Controller
public class ExampleController {
@RequestMapping("/")
public void handleRequest () {
//just for testing
throw new RuntimeException();
}
@RequestMapping("/test")
@ResponseBody
public String testHandler () {
return "test body";
}
}
src/main/webapp/WEB-INF/pages/error-page.jsp
<%@ page language="java"
contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<body>
<h3>This is example exception page</h3>
<p>Exception: <b>${exceptionType}</b></p>
<p>Handler method: <b> ${handlerMethod} </b></p>
</body>
</html>
Running the application
We are going to run the embedded tomcat server:
mvn clean install tomcat7:run-war
output
Exception thrown in our HandlerInterceptor:
HandlerExceptionResolver.resolveException won't be invoked at the http status error e.g. 404 error
Example ProjectDependencies and Technologies Used: - spring-webmvc 4.3.5.RELEASE: Spring Web MVC.
- javax.servlet-api 3.0.1 Java Servlet API
- JDK 1.8
- Maven 3.3.9
|