Last Updated on 17 May 2020   |   Print Email
This Spring tutorial helps you understand how to handle exceptions in a Spring MVC web application with code examples.You know, in Spring MVC, unexpected exceptions might be thrown during execution of its controllers. Spring provides two approaches for handling these exceptions:
Using XML configuration: this is similar to exception handling in Servlet/JSP, by declaring a SimpleMappingExceptionResolverbean in Spring’s application context file and map exception types with view names. This approach applies to all controllers in the application.
Using exception handler method: Spring provides the @ExceptionHandler annotation type which is used to annotate a method to handle exceptions raised by the controller’s methods. This approach applies to only the controller in which the handler method is declared.
Let’s look at each approach in details.
1. Using XML configuration
This approach uses XML to configure exceptions handling declaratively. Consider the following bean declaration in Spring’s application context file:
That will map any exceptions of type java.lang.ArithmeticException (or its sub types) to the view named MathError. During execution of a Spring controller, if such an exception is thrown, the client will be redirected to the mapped view. For example, if we configure a view resolver likes this:
Then Spring will redirect the client to the page /WEB-INF/views/MathError.jsp in case a java.lang.ArithmeticException exception is thrown. Accessing the exception in the MathError.jsp page as follows:
Arithmetic Error: ${exception}
Assuming we have the following controller class:
@Controller
@RequestMapping("/doMath")
public class MathController {
@RequestMapping(method = RequestMethod.GET)
public ModelAndView calculateSum(@RequestParam int a, @RequestParam int b) {
ModelAndView model = new ModelAndView("MathResult");
model.addObject("sum", (a + b));
model.addObject("subtract", (a - b));
model.addObject("multiply", (a * b));
model.addObject("divide", (a / b));
return model;
}
}
The method calculateSum() will handle the request /doMath, it takes two numbers a and b from the request and calculates sum, subtract, multiply and divide of them. The results are added to the model of the view called “MathResult”. In this code, there are two possible exceptions:
Either a or b is not a number.
b is zero, so the operation a / b will throw a java.lang.ArithmeticException exception.
Output when testing the application with two numbers a = 2000 and b = 100: If we pass b = 0, then the MathError.jsp page will be displayed: We can configure a default error view for all exceptions which are not specified in the exceptionMappings property, by specifying a view name for the defaultErrorView property. For example:
That tells Spring to redirect the client to the Error.jsp page if any exceptions other than the java.lang.ArithmeticException is thrown. Code of the Error.jsp page is similar to the MathError.jsp page:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>Error</title>
</head>
<body>
<h3>
General Error: ${exception}
</h3>
</body>
</html>
Output when testing the application with a = 2000 and b = ten (not a number):As we can see, the Error.jsp page is displayed because the exception thrown is of type TypeMismatchException, not ArithmeticException.We also can specify multiple mappings for exception types - view names as follows:
This approach uses the @ExceptionHandler annotation to annotate a method in controller class to handle exceptions raised during execution of the controller’s methods. Consider the following controller class:
@Controller
public class FileUploadController {
@RequestMapping(value = "/uploadFile", method = RequestMethod.GET)
public String doFileUpload(@RequestParam int a) throws IOException, SQLException {
// handles file upload stuff...
if (a == 1) {
throw new IOException("Could not read upload file.");
} else if (a == 2) {
throw new SQLException("Database exception!!!");
}
return "done";
}
@ExceptionHandler({IOException.class, java.sql.SQLException.class})
public ModelAndView handleIOException(Exception ex) {
ModelAndView model = new ModelAndView("IOError");
model.addObject("exception", ex.getMessage());
return model;
}
}
The method doFileUpload() may throw an IOException, and the handler method is declared as follows:
@ExceptionHandler(IOException.class)
public ModelAndView handleIOException(IOException ex) {
ModelAndView model = new ModelAndView("IOError");
model.addObject("exception", ex.getMessage());
return model;
}
This handleIOException() method will be invoked whenever an exception of type java.io.IOException (or its sub types) is raised within the controller class. Spring will pass the exception object into the method’s argument.Using exception handler method is very flexible, as it allows us doing some processing before returning to the error view. We can also pass additional information to the view’s model when necessary, for example:
model.addObject("info", "extra info for the exception");
It’s also possible to specify a list of exception classes in the @ExceptionHanlder annotation, for example:
@ExceptionHandler({IOException.class, java.sql.SQLException.class})
public ModelAndView handleIOException(Exception ex) {
ModelAndView model = new ModelAndView("IOError");
model.addObject("exception", ex.getMessage());
return model;
}
If the exception being thrown is one of the types (or sub types) in the list, the annotated method will be invoked. In the code above, if the exception is either of type IOException or SQLException, then the handleIOException() method will be invoked.
3. Conclusion
Using XML configuration (declaration of SimpleMappingExceptionResolverbean) will apply exception handling rules for the entire application, whereas using handler method (annotated by @ExceptionHandler annotation) will have effect only within the enclosing controller class. The XML declaration approach takes precedence over the annotation approach, so if we declared a SimpleMappingExceptionResolverbean in Spring’s application context file, then any @ExceptionHandler annotations will be ignored.
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.
But if you use "@ControllerAdvice" for your Exception class, it will handle the declared Exception for all your classes that are annotated with "@Controller".
Comments
Rethrow the exceptions up to the view layer and handle them in the view layer.