Spring - Exception Handling

springmvc

// Spring MVC - Exception handling:

There are 3 ways to handle exceptions in Spring:

1. Using the @ControllerAdvice annotation
2. Controller Specific Exception Handling
3. Use Aspect Oriented Programming

@ControllerAdvice       // Use for exception handling.  Create a class name 
        // ExceptionController.  Actually, the name of the class
        // does not matter.  Add the @ControllerAdvice and the @EnableWebMvc
        // annotations to this class.  Inside this class, we add:
        // @ExceptionHandler(value = Exception.class)
        // public String handleError(HttpServletRequest req, Exception exception) {
        //      return "error";
        // }
        // The @ControllerAdvice annotation tells Spring to advice all controllers
        // to use this class to handle exceptions.  The @ExceptionHandler annotation
        // specifies the type of exception that the handleError method can handle.
        // In this case, we specified Exception.class, which means that this method
        // can handle all types of exception.

@EnableWebMvc           // Use for exception handling

Using the @ControllerAdvice annotation
Create a Java class somewhere like 
/src/main/java/com/companyName/common/ExceptionController.java:

import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@ControllerAdvice
@EnableWebMvc
public class ExceptionController {
    @ExceptionHandler(value = Exception.class)
    public String handleError(HttpServletRequest req, Exception exception) {
        return "error";
    }
}

Notice that we use the @ControllerAdvice. This advice all the controllers to 
use this class to handle exceptions. We also use the @ExceptionHandler 
annotation and specify Exception.class as the value for the @ExceptionHandler 
annotation. This indicates the type of exception that this class can handle. 
Here we use Exception.class, which means that this class can handle all 
exceptions.

To implement Controller Specific Exception Handling:
This is similar to using the @ControllerAdvice annotation, but instead of 
adding the @ControllerAdvice annotation, just add to the individual 
controller class:

@ExceptionHandler(value = Exception.class)
public String handleError(HttpServletRequest req, Exception exception) {
    return "error";
}

What are the 3 recommended ways to handle exceptions in Spring?

  1. Using the @ControllerAdvice annotation
  2. Controller Specific Exception Handling
  3. Use Aspect Oriented Programming. See spring-aop

What is the best practice regarding exception handling?

Do not handle the exception unless you really add some value to it.

How can we implement exception handling using the @ControllerAdvice annotation?

Create a Java class somewhere like /src/main/java/com/in28minutes/common/ExceptionController.java:

package com.in28minutes.common;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@ControllerAdvice
@EnableWebMvc
public class ExceptionController {

    private Log logger = LogFactory.getLog(ExceptionController.class);

    @ExceptionHandler(value = Exception.class)
    public String handleError(HttpServletRequest req, Exception exception) {
        logger.error("Request: " + req.getRequestURL() + " raised " + exception);
        return "error";
    }
}

The name of the class does not really matter. In this case, the name is ExceptionController, which is appropriate enough. Notice that we use the @ControllerAdvice. This advice all the controllers to use this class to handle exceptions. We also use the @ExceptionHandler annotation and specify Exception.class as the value for the @ExceptionHandler annotation. This indicates the type of exception that this class can handle. Here we use Exception.class, which means that this class can handle all exceptions.

What is the meaning of the @ControllerAdvice annotation?

It gives advice to all controllers.

How can we implement controller-specific exception handling?

This is similar to using the @ControllerAdvice annotation, but instead of adding the @ControllerAdvice annotation, just add to the individual controller class:

@ExceptionHandler(value = Exception.class)
public String handleError(HttpServletRequest req, Exception exception) {
    logger.error("Request: " + req.getRequestURL() + " raised " + exception);
    return "error";
}

How can we handle exceptions that occur inside our JSP file?

Add:

<error-page>
    <location>/WEB-INF/views/error.jsp</location>
</error-page>

to our web.xml file:

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <display-name>To do List</display-name>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/todo-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

   <filter>
            <filter-name>springSecurityFilterChain</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
   </filter>

   <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
            <url-pattern>/*</url-pattern>
   </filter-mapping> 

    <error-page>
        <location>/WEB-INF/views/error.jsp</location>
    </error-page>
</web-app>

The above code show where we should add the <error-page> directive. Look at the last part of the code. The /src/main/webapp/WEB-INF/views/error.jsp should look like:

<%@ include file="common/header.jspf"%>
<%@ include file="common/navigation.jspf"%>
<div class="container">
    Application has encountered an error. Please contact support on ...
</div>
<%@ include file="common/footer.jspf"%>
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License