In some badly coded applications, when an unknown exception occurs then application server usually displays the evil exception stack trace to the user in webpage itself. In this case, users have nothing to do with this stack trace and complain that your application is not user friendly. Moreover, it can also prove a potential security risk, as you are exposing the internal method call hierarchy to users. Though a web application’s web.xml
can be configured to display friendly JSP pages in case an HTTP error or class exception occur, Spring MVC supports a more robust approach to managing views for class exceptions.
HandlerExceptionResolver and SimpleMappingExceptionResolver
In a Spring MVC application, you can register one or more exception resolver beans in the web application context to resolve uncaught exceptions. These beans have to implement the HandlerExceptionResolver
interface for DispatcherServlet
to auto-detect them. Spring MVC comes with such a simple exception resolver i.e. SimpleMappingExceptionResolver
to map each category of exceptions to a view in a configurable way.
Let’s say we have an exception class i.e. AuthException
. And we want that everytime this exception is thrown from anywhere into application, we want to show a pre-determined view page /WEB-INF/views/error/authExceptionView.jsp
. So the configuration would be.
SimpleMappingExceptionResolver configuration
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="com.howtodoinjava.demo.exception.AuthException"> error/authExceptionView </prop> </props> </property> <property name="defaultErrorView" value="error/genericView"/> </bean>
The complete context configuration is :
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.howtodoinjava.demo" /> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="messages" /> </bean> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="com.howtodoinjava.demo.exception.AuthException"> error/authExceptionView </prop> </props> </property> <property name="defaultErrorView" value="error/genericView"/> </bean> </beans>
Notice the “defaultErrorView” property in last. If spring context detects any exception thrown from application which is not listed into “exceptionMappings” properties list, then it will render the view /WEB-INF/views/error/genericView.jsp
.
Test SimpleMappingExceptionResolver Configured Application
For testing purpose, let’s create AuthException.java
.
AuthException.java
package com.howtodoinjava.demo.exception; import java.util.Date; public class AuthException extends RuntimeException { private static final long serialVersionUID = 1L; private Date date; private String message; public AuthException(Date date, String message) { super(); this.date = date; this.message = message; } public Date getDate() { return date; } public String getMessage() { return message; } @Override public String toString() { return "AuthException [date=" + date + ", message=" + message + "]"; } }
And throw this exception from any controller.
EmployeeController.java
@Controller @RequestMapping("/employee-module") public class EmployeeController { @RequestMapping(value="/getAllEmployees", method = RequestMethod.GET) public String welcome(Model model) { throw new AuthException(new Date(), "Something bad happened dude !! Run Away :-("); } }
And create two jsp files in path /WEB-INF/views/error/
authExceptionView.jsp
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <title>Authentication Exception</title> </head> <body> <h2>Exception occured at: </h2><fmt:formatDate value="${exception.date}" pattern="yyyy-MM-dd" /> <h2>Exception Message : </h2>${exception.message} </body> </html>
genericView.jsp
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <html> <head> <title>Generic Exception</title> </head> <body> <h2>Some generic error message</h2> </body> </html>
And now hit the URL : http://localhost:8080/springmvcexample/employee-module/getAllEmployees

Now throw any other exception from controller such as NullPointerException
as below.
@Controller @RequestMapping("/employee-module") public class EmployeeController { @RequestMapping(value="/getAllEmployees", method = RequestMethod.GET) public String welcome(Model model) { throw new NullPointerException(); } }
And hit again the URL : http://localhost:8080/springmvcexample/employee-module/getAllEmployees
Clearly, application is now able to find correct views in case of exceptions. No more error stack traces in front view.
Happy Learning !!