Spring MVC @ExceptionHandler Example
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.
2. Custom Exception
A custom exception, with custom error code and error description.
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 :
- If user provide a
/error
request, it throws “CustomGenericException”, and thehandleCustomException()
method will be fired. -
If user provide a
/io-error
request, it throws “IOException”, and thehandleAllException()
method will be fired.
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
<%@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>
<%@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
2. http://localhost:8080/SpringMvcExample/error
3. http://localhost:8080/SpringMvcExample/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
.
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;
}
}
The “handle All exceptions” scenario does Not work as that language specifically implies.
That handler for Exception.class Only handles the class “Exception” specifically, not everything under Exception.
Nobody has bothered clarifying this absolutely critical detail and that’s rather annoying because it makes all the difference in the world whether “Exception.class” in your annotation covers ALL EXCEPTIONS, or literally just Exception.class itself.
Hi
How to return one dialog with message “this is Exception.class“ in function handleAllException
and my page stay.
Hi I need 2 Exception handler in spring mvc. One for Web APIs which return Error page with html tags. Othe for the REST API which will return custom json data in response. How could I have both in same web application. Currently web application works on default /error page for any error.
thanks
I am losing the stacktrace when the exception is handled in controlleradvice. Can you please advise?
How to deploy it in tomcat ? Please any body can help me. Thanks advance
nice tutorial thanks
Thanks !
This won’t catch any filter related exceptions that originate outside the controller scope, how would you handle exceptions in filter?
Nice! Can you tell me how to handle the AJAX call. Currently full error page is loaded in AJAX success dialog.
what is the code in javascript to go on picture’site and search images and display in a window
Thanks !
Is it possible to make a generic exception handler for any class? I would like to implement an ExceptionHandler type solution for a listener class.