Spring MVC
This example demonstrates how to modify Spring default HandlerExceptionResolvers functionality.
The use case we are going to use is: we will map Spring internal exceptions to a custom error page.
By default, Spring internal exceptions are processed by
DefaultHandlerExceptionResolver . This example will demonstrate, how to selectively modify the default behavior.
We will use
SimpleMappingExceptionResolver to achieve the desired results.
Prerequisite
Ordering and customization of default
HandlerExceptionResolvers
Creating SimpleMappingExceptionResolver and registering as a bean
@EnableWebMvc
@ComponentScan("com.logicbig.example")
public class AppConfig {
@Bean
HandlerExceptionResolver customExceptionResolver () {
SimpleMappingExceptionResolver s = new SimpleMappingExceptionResolver();
Properties p = new Properties();
//mapping spring internal error NoHandlerFoundException to a view name.
p.setProperty(NoHandlerFoundException.class.getName(), "error-page");
s.setExceptionMappings(p);
//uncomment following line if we want to send code other than default 200
//s.addStatusCode("error-page", HttpStatus.NOT_FOUND.value());
//This resolver will be processed before default ones
s.setOrder(Ordered.HIGHEST_PRECEDENCE);
return s;
}
@Bean
public ViewResolver viewResolver () {
InternalResourceViewResolver viewResolver =
new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
The above SimpleMappingExceptionResolver maps Spring internal NoHandlerFoundException to a custom page, the rest of the default functionality will be unchanged.
WebApplicationInitializer implementation
public class AppInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses () {
return new Class<?>[]{AppConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses () {
return null;
}
@Override
protected String[] getServletMappings () {
return new String[]{"/"};
}
@Override
protected FrameworkServlet createDispatcherServlet (WebApplicationContext wac) {
DispatcherServlet ds = new DispatcherServlet(wac);
//setting this flag to true will throw NoHandlerFoundException instead of 404 page
ds.setThrowExceptionIfNoHandlerFound(true);
return ds;
}
}
What is throwExceptionIfNoHandlerFound?
The exception NoHandlerFoundException will only be thrown if this flag of DispatcherServlet is set to true.
We are doing that by using DispatcherServlet#setThrowExceptionIfNoHandlerFound(true). By default this flag is false.
src/main/webapp/WEB-INF/views/error-page.jsp
D:\LogicBig\example-projects\spring-mvc\default-exception-resolver-customization\src\main\webapp\WEB-INF\views\error-page.jsp
The Controller
@Controller
public class ExampleController {
/**
* This will throw MissingPathVariableException with response code 500
*/
@RequestMapping("/test/{id}")
@ResponseBody
public String handleRequest (@PathVariable("testId") String id) {
return "id: "+id;
}
/**
* The exception should be processed by @ExceptionHandler method
*/
@RequestMapping("/test")
public String handleRequest2 () throws Exception {
throw new OperationNotSupportedException();
}
@ExceptionHandler
@ResponseBody
public String handleException (OperationNotSupportedException b) {
return "from @ExceptionHandler method: " + b ;
}
}
Run embedded tomcat
mvn tomcat7:run-war
output
URI: /test/{id}
This should throw MissingPathVariableException, which is not mapped by our SimpleMappingExceptionResolver.
The above exception is handled by DefaultHandlerExceptionResolver.
URI: /test
This should invoke handleException(..) method of our controller. This method is annotated with @ExceptionHandler and has parameter
of the matching exception.
This shows that ExceptionHandlerExceptionResolver is processed as expected.
Other URIs
Other URIs, would normally, return default tomcat 404 error page. In our case, we have set DispatcherServlet to throw NoHandlerFoundException, which is mapped to
"error-page" as set by our SimpleMappingExceptionResolver.
Let's see what's the response status code in
HTTPie
:
If SimpleMappingExceptionResolver doesn't set any status code explicitly then the code 200 is returned. If we want to return 404
instead, then we can use
SimpleMappingExceptionResolver#addStatusCode("error-page", 404);
Example Project
Dependencies 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
|