In this tutorial, we show you how to do exception handling in Spring MVC frameworks. Normally, we use @ExceptionHandler to decide which “view” should be returned back if certain exception is raised.

P.S This @ExceptionHandler class is available since Spring 3.0

1. Project Structure

Review the project directory structure, a standard Maven project.

directory structure

2. Custom Exception

A custom exception, with custom error code and error description.

CustomGenericException.java

package com.mkyong.web.exception;

public class CustomGenericException extends RuntimeException {

	private static final long serialVersionUID = 1L;

	private String errCode;
	private String errMsg;

	public String getErrCode() {
		return errCode;
	}

	public void setErrCode(String errCode) {
		this.errCode = errCode;
	}

	public String getErrMsg() {
		return errMsg;
	}

	public void setErrMsg(String errMsg) {
		this.errMsg = errMsg;
	}

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

}

3. Spring Controller

A Spring controller, review the execution-flows below :

  1. If user provide a /error request, it throws “CustomGenericException”, and the handleCustomException() method will be fired.
  2. If user provide a /io-error request, it throws “IOException”, and the handleAllException() method will be fired.
MainController.java

package com.mkyong.web.controller;

import java.io.IOException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
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 MainController {

	@RequestMapping(value = "/{type:.+}", method = RequestMethod.GET)
	public ModelAndView getPages(@PathVariable("type") String type)
		throws Exception {

	  if ("error".equals(type)) {
		// go handleCustomException
		throw new CustomGenericException("E888", "This is custom message");
	  } else if ("io-error".equals(type)) {
		// go handleAllException
		throw new IOException();
	  } else {
		return new ModelAndView("index").addObject("msg", type);
	  }

	}

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

		ModelAndView model = new ModelAndView("error/generic_error");
		model.addObject("errCode", ex.getErrCode());
		model.addObject("errMsg", ex.getErrMsg());

		return model;

	}

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

		ModelAndView model = new ModelAndView("error/generic_error");
		model.addObject("errMsg", "this is Exception.class");

		return model;

	}

}

4. JSP Pages

pages/index.jsp

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

	<c:if test="${not empty msg}">
		<h2>${msg}</h2>
	</c:if>
	
</body>
</html>
pages/error/generic_error.jsp

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

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

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

5. Testing

Review following 3 test cases :

1. http://localhost:8080/SpringMvcExample/anything

spring-exceptional-handle-result-normal

2. http://localhost:8080/SpringMvcExample/error

spring-exceptional-handle-result-error

3. http://localhost:8080/SpringMvcExample/io-error

spring-exceptional-handle-result-io-error

6. @ControllerAdvice Example

The above @ExceptionHandler example is only apply to a single controller, to apply it globally (all controllers), annotate a class with @ControllerAdvice.

GlobalExceptionController.java

package com.mkyong.web.controller;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import com.mkyong.web.exception.CustomGenericException;

@ControllerAdvice
public class GlobalExceptionController {

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

		ModelAndView model = new ModelAndView("error/generic_error");
		model.addObject("errCode", ex.getErrCode());
		model.addObject("errMsg", ex.getErrMsg());

		return model;

	}

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

		ModelAndView model = new ModelAndView("error/generic_error");
		model.addObject("errMsg", "this is Exception.class");

		return model;

	}
	
}

7. Download Source Code

References

  1. Spring @ExceptionHandler JavaDoc
  2. Spring @ControllerAdvice JavaDoc
  3. Spring MVC Exception Handling Example