Spring MVC Exception Handling using @ControllerAdvice annotation

error-spring-mvc-exception

Spring MVC provides a great way to handle exceptions and errors. @ExceptionHandler annotation is core to this feature. For each Spring controller we can simply define a method that automatically gets called if a given exception occurs. For example:

import org.springframework.web.bind.annotation.ExceptionHandler; //.. @ExceptionHandler(IOException.class) public String exception(Exception e) { //.. return "error"; }
Code language: Java (java)

Thus whenever an IOException is raised from any controller method will call the above method exception(). We mapped IOException.class to this method using @ExceptionHandler annotation.

One short coming of this annotation is that it only handles exception getting raised from the controller where it is defined. It will not handle exceptions getting raised from other controllers. However this is a way to overcome this problem. @ControllerAdvice annotation is at your service for that.

@ControllerAdvice annotation

This annotation is used to define @ExceptionHandler, @InitBinder, and @ModelAttribute methods that apply to all @RequestMapping methods.

import org.springframework.web.bind.annotation.ControllerAdvice; //.. @ControllerAdvice public class ExceptionControllerAdvice { @ExceptionHandler(Exception.class) public String exception(Exception e) { return "error"; } }
Code language: Java (java)

Thus if we define our @ExceptionHandler annotation on method in @ControllerAdvice class, it will be applied to all the controllers.

One thing worth noting here is that Spring configuration must define mvc namespace in order to identify @ControllerAdvice annotation. Thus you must define following in your spring-servlet.xml file.

<mvc:annotation-driven/>
Code language: HTML, XML (xml)

If you have defined just the <context:annotation-config /> it wouldn’t work. The @ControllerAdvice will simply wont be loaded. So always remember to use <mvc:annotation-driven/> in Spring configuration.

Let us check a complete tutorial.

Complete Tutorial

Now we know the concept, let us use it and create a Spring MVC based application to track page hits. We will use Cookie to track page hit counter.
For this tutorial I will be using following tools and technologies:

  1. Spring MVC 3.2.6.RELEASE
  2. Java 6
  3. Eclipse
  4. Maven 3
spring-exception-handling-project-structure

Following is the project structure.

Create and copy following file contents in the project structure.

Maven configuration: pom.xml

<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>net.viralpatel.spring</groupId> <artifactId>Spring_ExceptionHandler_example</artifactId> <packaging>war</packaging> <version>1.0.0-SNAPSHOT</version> <name>Spring_ExceptionHandler_example</name> <properties> <org.springframework.version>3.2.6.RELEASE</org.springframework.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <compileSource>1.6</compileSource> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <!-- Spring MVC --> <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> <!-- JSTL taglib --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.1.2</version> </dependency> </dependencies> <build> <finalName>Spring_ExceptionHandler_example</finalName> </build> <profiles> </profiles> </project>
Code language: HTML, XML (xml)

Maven configuration is simple. We just need Spring MVC and JSTL dependency.

Deployment description: web.xml

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Spring MVC Http Cookie</display-name> <welcome-file-list> <welcome-file>hello.htm</welcome-file> </welcome-file-list> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> </web-app>
Code language: HTML, XML (xml)

Web.xml is quite simple too. We just need to configure Spring’s DispatcherServlet with *.htm url pattern.

Spring configuration: spring-servlet.xml

<?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: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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven/> <context:component-scan base-package="net.viralpatel" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
Code language: HTML, XML (xml)

In spring-servlet.xml we just defined component scan to load @Controller classes. Also we defined a view resolver that will points to JSPs within /WEB-INF/jsp/ folder. As noted earlier, we defined <mvc:annotation-driven/> to load @ControllerAdvice classes.

Spring Controller

We will define one spring controller and one @ControllerAdvice class for this example. One is just to render a hello page with a link. On click of the link we invoke another controller method. This method however will throw an exception.

HelloController.java

package net.viralpatel.spring; import java.io.IOException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { @RequestMapping(value = "/hello.htm") public String hello() throws IOException { // render hello.jsp page return "hello"; } @RequestMapping(value = "/test.htm") public String test() throws IOException { //just throw exception to test the exceptionhandler mapping if(true) { throw new IOException("this is io exception"); } // render hello.jsp page return "hello"; } }
Code language: Java (java)

ExceptionControllerAdvice.java

package net.viralpatel.spring; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.servlet.ModelAndView; @ControllerAdvice public class ExceptionControllerAdvice { @ExceptionHandler(Exception.class) public ModelAndView exception(Exception e) { ModelAndView mav = new ModelAndView("exception"); mav.addObject("name", e.getClass().getSimpleName()); mav.addObject("message", e.getMessage()); return mav; } }
Code language: Java (java)

This class simply define a @ControllerAdvice and a method with @ExceptionHandler. This method will be called whenever an unhandled exception occurs.

JSP views

Two JSPs will be used. One for hello page and one which will be called in case of any error.

hello.jsp

<html> <head> <title>Spring MVC Exception Handling</title> </head> <body> <h1>Spring MVC Exception Handling</h1> <a href="test.htm">Click here to test Exception handling</a> </body> </html>
Code language: HTML, XML (xml)

exception.jsp

<html> <head> <title>Spring MVC @ControllerAdvice example</title> </head> <body> <h1>Ops! Something went wrong</h1> <b>${name}</b>: ${message} </body> </html>
Code language: HTML, XML (xml)

Demo

Compile and run the project. Open your favorite web browser and point to below URL:
http://localhost:8080/Spring_ExceptionHandler_example/hello.htm

spring-mvc-exception-handling-controlleradvice-demo

Once you click the link, the controller throws an exception which is handled nicely by @ExecptionHandler method.

spring-mvc-exception-handling-controlleradvice-demo2

Download Source Code

Spring_ExceptionHandler_example.zip (10 KB)

Get our Articles via Email. Enter your email address.

You may also like...

8 Comments

  1. sreenath says:

    Hi,
    Thanks for writing this tutorial.
    I am getting below exception while running my spring application, can guide me if i am doing anything wrong.
    org.xml.sax.SAXParseException: cos-all-limited.1.2: An ”all” model group must appear in a particle with ‘{‘min occurs’}’='{‘max occurs’}’=1, and that particle must be part of a pair which constitutes the ‘{‘content type’}’ of a complex type definition.
    at org.apache.xerces.parsers.DOMParser.parse(DOMParser.java:267)
    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:201)
    =====================
    below is my config file

  2. Sarala Rajagopalan says:

    Nicely complements this other useful blog post: http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

  3. Gautham says:

    Hi,

    I have done the setup but unfortunately my @ControllerAdvice Class is not handling the exceptions.
    I have a similar situation like below link.

    http://stackoverflow.com/questions/21884737/controlleradvice-not-firing

    Any help would be appreciated.

  4. priya says:

    please post a clear example on freemarker+springMVC with freemarker TemplateExceptionHandler.

    How to catch TemplateException raised in freemarker???

  5. sandy says:

    Hi,

    Nice example, Can i forward the exception message to the same jsp page instead of a seperate exception page ? If it is possible please let me know the way to do it.

    Thanks

  6. irving says:

    thx, this blog is quite useful for me.
    thx again

  7. JoonHo Kim says:

    thanks. very useful post…
    but 404(File Not Found) error is not rendered to the exception JSP file…

Leave a Reply

Your email address will not be published. Required fields are marked *