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
Tags :

About the Author

mkyong
Founder of Mkyong.com and HostingCompass.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

  • Pingback: plan()

  • Pingback: electricians scissors()

  • Pingback: electrician expat jobs in africa()

  • Pingback: house blue()

  • Pingback: Spring MVC Tutorial()

  • Pingback: water ionizer()

  • Pingback: stop parking()

  • Pingback: parking()

  • Pingback: mobile porn()

  • Pingback: laane penge()

  • Pingback: sms lan nu()

  • Pingback: Mischievous towheaded dame deep throating dude()

  • Pingback: online casinos()

  • Pingback: best online casinos()

  • Pingback: Blue Coaster33()

  • Sahar

    More than helpful, as always!
    Thanks a lot!

  • Sanjib

    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

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

    Thanks for sharing.

  • http://www.hcl.com Ganesh K Thiagarajan

    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

  • http://www.hcl.com Ganesh K Thiagarajan

    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

  • http://www.koallanerd.blogspot.com.br/ Allan Story

    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

    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

    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

  • http://www.sababagamesonline.com batz

    thx for the tutorial.

  • Jonatan

    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