Spring MVC Exception Handling – SimpleMappingExceptionResolver

Assume that the web application is throwing some exception from the backend and it is coming in the UI as below

How bad it is for the user to see this error right?
So we need to handle the exception gracefully in the application.
When we handle it properly , we can display the user friendly message.

Lets see how Spring MVC helps in Exception Handling

In Spring MVC,We can handle exception in many ways but we will see popular 3 ways

1)SimpleMappingExceptionResolver

This is the implementation of HandlerExceptionResolver class.
In this method , Each exception class will be mapped to specific view page.

2)Controller based ExceptionHandler

In this method,All the exceptions thrown by a specific controller can be handled by defining ExceptionHandler methods inside that controller. Any exceptions thrown outside that controller will not be handled here.

3)Global ExceptionHandler

In this method , All the exceptions thrown from any controller in the application can be handled by defining a single class which is annotated with @ControllerAdvice

Enough with the Theory , lets go ahead with each approach Step by Step.

1)SimpleMappingExceptionResolver

We will create a simple Login project to find the user based on user name. and if user enters invalid credentials we will throw an exception and will handle it gracefully.

Project structure

Create custom Exception class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.kb.exception;
 
public class InvalidUserException extends RuntimeException{
    
    private static final long serialVersionUID = 1L;
    
    private String errorCode;
    private String errorMessage;
 
    public InvalidUserException(String message) {
        this.errorMessage=message;
    }
    
    public InvalidUserException(String errorCode,String message) {
        this.errorCode = errorCode;
        this.errorMessage=message;
    }
 
    public String getErrorCode() {
        return errorCode;
    }
 
    public String getErrorMessage() {
        return errorMessage;
    }
 
}
package com.kb.exception;

public class InvalidUserException extends RuntimeException{
	
	private static final long serialVersionUID = 1L;
	
	private String errorCode;
	private String errorMessage;

	public InvalidUserException(String message) {
		this.errorMessage=message;
	}
	
	public InvalidUserException(String errorCode,String message) {
		this.errorCode = errorCode;
		this.errorMessage=message;
	}

	public String getErrorCode() {
		return errorCode;
	}

	public String getErrorMessage() {
		return errorMessage;
	}

}

Create the model class which holds user details

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.kb.model;
 
public class User {
 
    private String userName;
 
    private String password;
 
    public String getUserName() {
        return userName;
    }
 
    public void setUserName(String userName) {
        this.userName = userName;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
}
package com.kb.model;

public class User {

	private String userName;

	private String password;

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

}

Create the login controller class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.kb.controllers;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
import com.kb.exception.InvalidUserException;
import com.kb.model.User;
 
@Controller
public class LoginController {
 
    @RequestMapping(value="/displayLoginPage",method=RequestMethod.GET)
    public String displayLoginPage(Model model){
        User user = new User();
        model.addAttribute("user", user);
        return "/login";
    }
    
    @RequestMapping(value="/doLogin",method=RequestMethod.POST)
    public String doLogin(@ModelAttribute User user,Model model){
        
        String userName=user.getUserName();
        String password = user.getPassword();
        if("kb".equals(userName) && "1234".equals(password)){
            model.addAttribute("user", user);
            return "/home";
        }
        else{
            //Log the exception
            throw new InvalidUserException("INVALID_USER","User is not Valid for this site");
        }
        
    }
    
    @RequestMapping(value="/getGenericException",method=RequestMethod.GET)
    public String getGenericException(Model model) throws Exception{
 
        throw new Exception();
    }
}
package com.kb.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.kb.exception.InvalidUserException;
import com.kb.model.User;

@Controller
public class LoginController {

	@RequestMapping(value="/displayLoginPage",method=RequestMethod.GET)
	public String displayLoginPage(Model model){
		User user = new User();
		model.addAttribute("user", user);
		return "/login";
	}
	
	@RequestMapping(value="/doLogin",method=RequestMethod.POST)
	public String doLogin(@ModelAttribute User user,Model model){
		
		String userName=user.getUserName();
		String password = user.getPassword();
		if("kb".equals(userName) && "1234".equals(password)){
			model.addAttribute("user", user);
			return "/home";
		}
		else{
			//Log the exception
			throw new InvalidUserException("INVALID_USER","User is not Valid for this site");
		}
		
	}
	
	@RequestMapping(value="/getGenericException",method=RequestMethod.GET)
	public String getGenericException(Model model) throws Exception{

		throw new Exception();
	}
}

In the above controller, we have a method displayLoginPage() which displays the login page.

We also have a method doLogin() which checks the credentials and displays home page if credentials are valid.

If credentials are invalid , we throw an exception InvalidUserException which we handle as below.

There is one more method getGenericException() which is intentionally used to throw some general exception just to show how any unhandled exception is handled automatically through Exception resolver mapping.

Create the spring configuration file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
 
    <context:component-scan base-package="com.kb.*" />
    <mvc:annotation-driven />
     
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
    <bean
        class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <map>
                <entry key="InvalidUserException" value="userNotFound"/>
            </map>
        </property>
        <property name="defaultErrorView" value="genericError"/>
    </bean>
    
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
 
    <context:component-scan base-package="com.kb.*" />
    <mvc:annotation-driven />
     
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
    <bean
		class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<property name="exceptionMappings">
			<map>
                <entry key="InvalidUserException" value="userNotFound"/>
            </map>
		</property>
		<property name="defaultErrorView" value="genericError"/>
	</bean>
	
</beans>

So in the above file, we have defined SimpleMappingExceptionResolver, it has a property called exceptionMappings where we can specify the list of exceptions and their corresponding view page to display.

There is also a property called defaultErrorView which is very useful property,
It maps any other unhandled exceptions in the application to the corresponding view page(genericError.jsp in this case)

Create the login jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<title>Spring MVC Exception Handling</title>
</head>
 
<body>
    <h2>Enter below details to Login</h2>
 
    <form:form method="POST" modelAttribute="user" action="doLogin">
        <table>
            
            <tr>
                <td>Enter your User Name</td>
                <td><form:input path="userName" /></td>
            </tr>
            
            <tr>
                <td>Enter your password:</td>
                <td><form:password path="password"  showPassword="true"/></td>
            </tr>
            
            <tr>
                <td><input type="submit" name="submit" value="Click here to Login"></td>
            </tr>
        </table>
    </form:form>
 
</body>
</html>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<title>Spring MVC Exception Handling</title>
</head>

<body>
	<h2>Enter below details to Login</h2>

	<form:form method="POST" modelAttribute="user" action="doLogin">
		<table>
			
			<tr>
				<td>Enter your User Name</td>
				<td><form:input path="userName" /></td>
			</tr>
			
			<tr>
				<td>Enter your password:</td>
				<td><form:password path="password"  showPassword="true"/></td>
			</tr>
			
			<tr>
				<td><input type="submit" name="submit" value="Click here to Login"></td>
			</tr>
		</table>
	</form:form>

</body>
</html>

Create the home jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login Success</title>
</head>
<body>
 <div align="center">
        <h2>Welcome ${user.userName}! You have been successfully Logged in.</h2>
  </div>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login Success</title>
</head>
<body>
 <div align="center">
        <h2>Welcome ${user.userName}! You have been successfully Logged in.</h2>
  </div>
</body>
</html>

This home jsp is displaed after successful login.

Create the userNotFound jsp

1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h2> Sorry User is not valid for this site</h2>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h2> Sorry User is not valid for this site</h2>
</body>
</html>

The above jsp page is displayed when the user enters invalid credentials as we are throwing the InvalidUserException in the controller.

We are also mapping the InvalidUserException inside spring configuration file for the above jsp page.

Create the genericError jsp page

1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h2> Sorry, some technical error, Please try again</h2>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h2> Sorry, some technical error, Please try again</h2>
</body>
</html>

The above jsp page is displayed when any other exception apart from InvalidUserException is thrown.

Create the web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">
 
    <display-name>Simple Mapping Exception Resolver</display-name>
 
    <!-- Spring MVC dispatcher servlet -->
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
            /WEB-INF/spring-mvc.xml,
        </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
 
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
 
    <!-- Loads Spring Security configuration file -->
     <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring-mvc.xml,
        </param-value>
    </context-param>
</web-app>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1">

	<display-name>Simple Mapping Exception Resolver</display-name>

	<!-- Spring MVC dispatcher servlet -->
	<servlet>
		<servlet-name>mvc-dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
			/WEB-INF/spring-mvc.xml,
		</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>mvc-dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Loads Spring Security configuration file -->
	 <context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/spring-mvc.xml,
		</param-value>
	</context-param>
</web-app>

Create the pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>Spring</groupId>
  <artifactId>ExceptionHandling</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>ExceptionHandling Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <properties>
        <org.springframework.version>4.2.0.RELEASE</org.springframework.version>
    </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
 
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>javax.servlet.jsp.jstl-api</artifactId>
    <version>1.2.1</version>
</dependency>
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>
  </dependencies>
  <build>
    <finalName>SimpleMappingExceptionResolver</finalName>
    <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
  </build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>Spring</groupId>
  <artifactId>ExceptionHandling</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>ExceptionHandling Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <properties>
		<org.springframework.version>4.2.0.RELEASE</org.springframework.version>
	</properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
	<groupId>javax.servlet.jsp.jstl</groupId>
	<artifactId>javax.servlet.jsp.jstl-api</artifactId>
	<version>1.2.1</version>
</dependency>
<dependency>
	<groupId>taglibs</groupId>
	<artifactId>standard</artifactId>
	<version>1.1.2</version>
</dependency>
  </dependencies>
  <build>
    <finalName>SimpleMappingExceptionResolver</finalName>
    <plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.5.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
  </build>
</project>

Now deploy the project in web server and access the below url

http://localhost:8080/SimpleMappingExceptionResolver/displayLoginPage

Enter username as kb and password as 1234
Home page is displayed, no issues.

Enter invalid credentials , I am giving username as xyz and password as 1111 as below

Now see the output

The above view page is coming from userNotFound.jsp.

When the user enters invalid credentials, our login controller will throw InvalidUserException and
We have configured the same exception in spring configuration file for the userNotFound.jsp

Now access the below url which actually throws general exception

http://localhost:8080/SimpleMappingExceptionResolver/getGenericException

Just to see how any unhandled exceptions are handled by SimpleMappingExceptionResolver by using the property ‘defaultErrorView’.

see the output

See that , the view page coming here is genericError.jsp

As spring configuration file is defined with Exception resolver and
defaultErrorView is mapped to genericError.jsp, the above view page is displayed.

About the Author

Karibasappa G C (KB)
Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on