Main Tutorials

Spring MVC Exception Handling Example

In J2EE / servlet web application, you can map error page to specify exception like this :

web.xml

  <error-page>
	<error-code>404</error-code>
	<location>/WEB-INF/pages/404.jsp</location>
  </error-page>

  <error-page>
	<exception-type>com.mkyong.web.exception.CustomException</exception-type>
	<location>/WEB-INF/pages/error/custom_error.jsp</location>
  </error-page>
	
  <error-page>
	<exception-type>java.lang.Exception</exception-type>
	<location>/WEB-INF/pages/generic_error.jsp</location>
  </error-page>
  

The above code should be self-exploratory. If the exception handling function exists in the servlet container, why we still need to use the Spring to handle the exception?

Generally, there are two reasons :

  1. Customize Error Page – The servlet container will render the error page directly; While the Spring allows you to populate model or data to the error page, so that you can customize a more user friendly error page.
  2. Business logic – Spring allow you to apply extra business logic before rendering the error page, like logging, auditing and etc.

In this tutorial, we will show you two examples to handle the exception in Spring.

  1. For Spring 2.x, we use SimpleMappingExceptionResolver in the XML file.
  2. For Spring 3.x, we can simplify the XML configuration via @ExceptionHandler annotation.

1. SimpleMappingExceptionResolver Example

Review the directory structure.

spring-mvc-exception-example-directory

A custom exception.

CustomGenericException.java

package com.mkyong.web.exception;

public class CustomGenericException extends RuntimeException {

	private static final long serialVersionUID = 1L;

	private String errCode;
	private String errMsg;

	//getter and setter methods

	public CustomGenericException(String errCode, String errMsg) {
		this.errCode = errCode;
		this.errMsg = errMsg;
	}

}

This controller class, just throw a CustomGenericException with custom error code and error description.

CustomerController.java

package com.mkyong.web.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import com.mkyong.web.exception.CustomGenericException;

public class CustomerController extends AbstractController {

  @Override
  protected ModelAndView handleRequestInternal(HttpServletRequest request,
	HttpServletResponse response) throws Exception {

	throw new CustomGenericException("E888", "This is custom message - ABC");

  }

}

Review the SimpleMappingExceptionResolver below :

mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	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.0.xsd
        http://www.springframework.org/schema/mvc 
	http://www.springframework.org/schema/mvc/spring-mvc-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.mkyong" />

	<bean
	class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>

	<!-- Register the bean -->
	<bean class="com.mkyong.web.controller.CustomerController" />

	<bean
	  class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	  <property name="exceptionMappings">
		<props>
			<prop key="com.mkyong.wb.exception.CustomGenericException">
				error/generic_error
			</prop>
			<prop key="java.lang.Exception">error/exception_error</prop>
		</props>
	  </property>
	</bean>

	<bean
	  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/pages/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>

	<mvc:annotation-driven />

</beans>

In above, when

  1. CustomGenericException is thrown, it will map to the view name “error/generic_error”.
  2. Any other Exceptions is thrown, it will map to the view name “error/exception_error”.

In the JSP page, you can access the exception instance via ${exception}.

pages/error/generic_error.jsp.jsp

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>

	<c:if test="${not empty exception.errCode}">
		<h1>${exception.errCode} : System Errors</h1>
	</c:if>
	
	<c:if test="${empty exception.errCode}">
		<h1>System Errors</h1>
	</c:if>

	<c:if test="${not empty exception.errMsg}">
		<h2>${exception.errMsg}</h2>
	</c:if>
	
</body>
</html>

Demo – http://localhost:8080/SpringMvcExample/customer

spring-mvc-exception-handle-1

2. @ExceptionHandler Example

Since Spring 3.0, there is a new annotation @ExceptionHandler to simplify the XML configuration. Below is the equivalent version using @ExceptionHandler.

CustomerController.java

package com.mkyong.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.mkyong.web.exception.CustomGenericException;

@Controller
public class CustomerController {

	@RequestMapping(value = "/customer", method = RequestMethod.GET)
	public ModelAndView getPages() throws Exception {

		throw new CustomGenericException("E888", "This is custom message X");

	}

	@ExceptionHandler(CustomGenericException.class)
	public ModelAndView handleCustomException(CustomGenericException ex) {

		ModelAndView model = new ModelAndView("error/generic_error");
		model.addObject("exception", ex);
		return model;

	}

	@ExceptionHandler(Exception.class)
	public ModelAndView handleAllException(Exception ex) {

		ModelAndView model = new ModelAndView("error/exception_error");
		return model;

	}

}

Nothing to declare in Spring XML file.

mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	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.0.xsd
        http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-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.mkyong" />

	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/pages/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>

	<mvc:annotation-driven />

</beans>
Note
You may interest at this Spring MVC @ExceptionHandler Example

Reference

  1. SimpleMappingExceptionResolver JavaDoc
  2. @ExceptionHandler JavaDoc
  3. Spring MVC @ExceptionHandler Example

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
14 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
danstorre
9 years ago

I got to say Man mkyong you’re great thaks for this tutorial!

Houssem KHALDI
5 years ago

Very Helpful !!

arun singh
6 years ago

thanks for the information.

Erico Souza
7 years ago

it’s great, but you have a example that don’t use web.xml, and the configuration it’s in java code, extends AbstractAnnotationConfigDispatcherServletInitializer or extends WebMvcConfigureAdapter?

Sahar
10 years ago

More than helpful, as always!
Thanks a lot!

Sanjib
10 years ago

Hi MK,

This solution is working only for those methods in controller which has ModelAndView as return type ,but in case of Responseentity this exception handling is not working.

Please tell how to show that error page if the exception has occurred in Response entity return type method.

Thankx

Sandeep
11 years ago

Thanks Yong..
have read atleast 4 articles of urs which have helped me learn concepts very fast.

Thanks for sharing.

Ganesh K Thiagarajan
11 years ago

Dear MkYong

Our application has the following layers and interaction:

View (JSP) -> Ajax calls -> MyController (implements Spring Controller) -> through a custom service lookup -> MyService (implements Base Service) -> My DAOimpl

Our idea is to use AOP for logging exceptions. To keep the AOP intercepts simple, we decided to define the cuts on the Controllers. The Controllers have a few methods like onLoad, onUpdate (related to CRUD ops) which are called from the handleRequest method, and we would like to define these methods for the poitncut.
Ie., any exception at the Service layer or below, will bubble up and will reach the Controllers. AOP pointcut defined to intercept the throws exception and log the exception details into a log. Subsequently, an error code will be sent back to the view where the error message will be displayed appropriately.

Issues:
– AOP does not intercept the calls to the onLoad, etc methods. We understand that this is because calls to these methods from handleRequest are treated as self calls on the Controller and hence AOP does not intercept them.
– To circumvent the issue above, we created an interface with onLoad, onUpdate methods and a set of util classes that implement the onLoad, etc methods. The Controllers will have these utils as members. Pointcuts will be defined on these utils instead of the Controllers. When doing this, AOP works only if the AOP config is present in the spring-servlet xml and not in a custom xml for AOP declaration. This observation is only for Controllers. If the AOP cuts are defined on Service layer, then the declarations work as expected (in a custom xml). We are not sure of the dependency between spring servlet xml and the cuts on Controllers.

Suggestions required:
– Should we have AOP defined for Controllers at all? Should this be defined only at Service layer? At the Controllers, the exceptions will be ‘caught’ and the error message will be sent to view appropriately. Wanted to check if there are any fundamental issues in the original approach.

Regards
Ganesh K Thiagarajan

Ganesh K Thiagarajan
11 years ago

Hi ,
I would like to apply AOP for logging the error messages using Spring Framework. By configuring for service and dao layers AOP happens to work for what so ever methods configured, but fails in Controller Layer.
Experimented with in Controller ,but noticed the cut happens only with the handelRequest().

Please advice me on how to apply on methods that are defined by me..
Ex: I have methods by name onLoad(), onSave()…

public class MyController extends BaseController(){
public void onLoad(…){}
public void onSave(…){}
}

public class BaseController implements Controller{
public abstract void onLoad(…);
public abstract void onSave(…);
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
// upon conditions will call the abstract methods…
}
}

Pls advice..

Regards
Ganesh K Thiagarajan

Allan Story
11 years ago

hello guys! this is an awesome tutorial, thanks!

but I have a doubt, is possible in case of a com.mkyong.common.exception.GenericException, redirect the “process” for a Controller?

This example for this is that every error generated send an email to the web master.

Thank you in advance!

Anshu
11 years ago

how can i get a common error page to handle any exception than doesn’t lies within the defined exceptions in our xml file.

Chandrakant
11 years ago

Thank you so much for your help I did the same but I got stuck in one problem
Please help me out.
When java runtime exception rised then the error page get open in the parent dialog.
I want to open error.jsp file in new tab as well as I want to close the session and redirect user to login page!!!
How can I achieve this??
Please help

batz
13 years ago

thx for the tutorial.

Jonatan
13 years ago

First of all, thanks a lot for your tutorials. You are doing a very good job sharing this and I really appreciate.

I found a strange behavior using UrlBasedViewResolver with an specific viewClass, for Tiles2 purposes, instead of InternalResourceViewResolver. Its always resolved to the prop defined with the java.lang.Exception and never goes to the xxx.xxx.xxx.GenericException.
One thing I’ve noticed is when I put a breakpoint in the handleRequestInternal of the controller class, the program never stops there when an exception is produced.

Do you have any idea why may be the reason?

TIA