JavaBlog.fr / Java.lu DEVELOPMENT,Java,Spring,WEB Java/Spring MVC: Exception Handler, Resolver and Customization

Java/Spring MVC: Exception Handler, Resolver and Customization

Hello,

In this article, I would present you the exception handling and resolving of Spring MVC in a web application. Usually, it’s recommended to display a error page instead of the default long java plain exception code in web application. So, it is possible to configure a custom error page to map a specified error code or exception type in the classic web.xml of servlet container:

1<error-page>
2    <error-code>404</error-code>
3    <location>/WEB-INF/jsp/my404.jsp</location>
4</error-page>
5  
6<error-page>
7    <exception-type>java.lang.Exception</exception-type>
8    <location>/WEB-INF/jsp/my404.jsp</location>
9</error-page>

However, the Spring framework proposes a resolving system of exception, relative to the previous system of the servlet container, via the data population because Spring allows the population of model for the error page with specific data: title, message…etc.

But, often, it could be necessary to apply extra business logic like sending an email to administrators, logging, auditing before render the error page when an exception is thrown from business layer. So, in this tutorial, we will extend the class provided by Spring SimpleMappingExceptionResolver to do the exception handling in Spring MVC application.

1. Custom exceptions
Create two simple customized exceptions:

01package com.ho.exceptionresolver;
02//...
03public class MyBusinessException extends Exception {
04 
05    public MyBusinessException() {
06    }
07 
08    public MyBusinessException(String message) {
09        super(message);
10    }
11 
12    public MyBusinessException(Throwable cause) {
13        super(cause);
14    }
15 
16    public MyBusinessException(String message, Throwable cause) {
17        super(message, cause);
18    }
19 
20    // ...
21}

and

01package com.ho.exceptionresolver;
02//...
03public class MyTechnicalException extends Exception {
04 
05    public MyTechnicalException() {
06    }
07 
08    public MyTechnicalException(String message) {
09        super(message);
10    }
11 
12    public MyTechnicalException(Throwable cause) {
13        super(cause);
14    }
15 
16    public MyTechnicalException(String message, Throwable cause) {
17        super(message, cause);
18    }
19 
20    // ...
21}

2. Presentation Layer
For our tutorial :), we will throw a MyBusinessException exception and a MyTechnicalException exception in the controller class MyController:

01package com.ho.exceptionresolver;
02//...
03public class MyController extends MultiActionController{
04  
05    public ModelAndView handleRequest1(HttpServletRequest request, HttpServletResponse response) throws Exception {
06        //...
07        throw new MyBusinessException("Heyyy...a business exception message");
08        //...
09    }
10 
11    public ModelAndView handleRequest2(HttpServletRequest request, HttpServletResponse response) throws Exception {
12        //...
13        throw new MyTechnicalException("Heyyy...a technical exception message");
14        //...
15    }
16    // ...
17}

3. Extend SimpleMappingExceptionResolver
Then, we will create a custom class named CustomSimpleMappingExceptionResolver extending the Spring class SimpleMappingExceptionResolver and overrides its doResolveException method. The goals of this class will be:

  • get all exceptions (+customization) thrown in the Spring controllers,
  • set the specific error parameters (“errorTitle” and “errorMessage”) depending of the exception type,

In the doResolveException method, we could apply extra business logic (auditing, logging or sending emails) depending on type of exception MyBusinessException, MyTechnicalException and Exception.

01package com.ho.exceptionresolver;
02 
03import org.springframework.web.servlet.ModelAndView;
04import java.lang.Exception;
05import javax.servlet.http.HttpServletRequest;
06import javax.servlet.http.HttpServletResponse;
07import java.lang.Object;
08 
09import com.ho.exceptionresolver.MyBusinessException;
10 
11 
12public class CustomSimpleMappingExceptionResolver extends SimpleMappingExceptionResolver{
13 
14    //-------------------------------- CONSTRUCTOR
15    public CustomSimpleMappingExceptionResolver (){
16        super();
17    }
18 
19    //-------------------------------- PROTECTED METHODS
20    @Override
21    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){
22 
23        ModelAndView modelAndView = super.doResolveException(request, response, handler, ex);
24         
25        String errorTitle = "";
26         
27        if(ex instanceof MyBusinessException){
28            errorTitle = "A specific title for the MyBusinessException exception";
29            // ... Apply extra business logic: auditing, logging
30            // ...... for the MyBusinessException exception
31 
32 
33        }else if(ex instanceof MyTechnicalException){
34            errorTitle = "A specific title for the MyTechnicalException exception";
35            // ... Apply extra business logic: sending emails
36            // ...... for the MyTechnicalException exception
37 
38        }else{
39            errorTitle = "Error standard exception";
40        }
41 
42        modelAndView.getModelMap().addAttibute("errorTitle", errorTitle );
43        modelAndView.getModelMap().addAttibute("errorMessage", ex.getMessage());       
44         
45        return modelAndView;
46    }
47    // ...
48}

4. Spring Configuration
In Spring’s bean configuration file, we will declare a InternalResourceViewResolver and the CustomSimpleMappingExceptionResolver class which maps:

  • the “MyBusinessException” exception to the view name “businessErrorPage” for the “/WEB-INF/jsp/businessErrorPage.jsp”,
  • the “MyTechnicalException” exception to the view name “technicalErrorPage” for the “/WEB-INF/jsp/technicalErrorPage.jsp” page,
  • any Exception or its sub class to the view name “rrorPage” for the “/WEB-INF/jsp/errorPage.jsp” page,
01<!-- ################### SPRING MVC VIEW RESOLVER  ################### -->
02<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
03    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
04    <property name="prefix" value="/WEB-INF/jsp/"></property>
05    <property name="suffix" value=".jsp"></property>
06    <property name="order"><value>2</value></property>
07</bean>
08 
09<!-- ################### EXCEPTION RESOLVER ################### -->
10<bean name="myExceptionResolver" class="com.ho.exceptionresolver.CustomSimpleMappingExceptionResolver">
11    <property name="exceptionMappings">
12        <props>
13            <prop key="com.ho.exceptionresolver.MyBusinessException">businessErrorPage</prop>
14            <prop key="com.ho.exceptionresolver.MyTechnicalException">technicalErrorPage</prop>
15            <prop key="java.lang.Exception">errorPage</prop>
16        </props>
17    </property>
18</bean>

Note: If a handler is configured for the java.lang.Exception in both Spring and servlet container, then, the Spring configration will have more high priority to handle the exception.

1<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
2    <property name="exceptionMappings">
3    <props>
4        <prop key="java.lang.Exception">errorPage</prop>
5    </props>
6    </property>
7</bean>

File: web.xml

1<error-page>
2    <exception-type>java.lang.Exception</exception-type>
3    <location>/WEB-INF/jsp/errorPage.jsp</location>
4</error-page>

5. View Pages
Here, the code of view JSP pages which display the parameters errorTitle and errorMessage added in the CustomSimpleMappingExceptionResolver:
File businessErrorPage.jsp for the MyBusinessException:

01<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
02<html>
03<head>
04<title>Error page</title>
05</head>
06<body>
07------- Business Error Page -------
08<h1>${errorTitle}</h1>
09<hr/>
10<b>${errorMessage}</b>
11</body>
12</html>

File technicalErrorPage.jsp for the MyTechnicalException:

01<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
02<html>
03<head>
04<title>Error page</title>
05</head>
06<body>
07------- Technical Error Page -------
08<h1>${errorTitle}</h1>
09<hr/>
10<b>${errorMessage}</b>
11</body>
12</html>

File errorPage.jsp for the java.lang.Exception:

01<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
02<html>
03<head>
04<title>Error page</title>
05</head>
06<body>
07------- Java Exception -------
08<% -- <h1>${exception.customMessage}</h1> --%>
09<h1>${errorTitle}</h1>
10<hr/>
11<b>${errorMessage}</b>
12</body>
13</html>

Note: In a JSP page, the exception instance could be accessed via ${exception} EL expression.

6. Other solution
It is possible to handle the exception in presentation layer (Controller) without use of the class “SimpleMappingExceptionResolver” only by create an abstract class MyAbstractController extending the Spring class MultiActionController, and extended by the others Spring controllers in the application. We will override the handleRequestInternal method with a simple try/catch:

01package com.ho.exceptionresolver;
02 
03//...
04public abstract class MyAbstractController extends MultiActionController{
05     
06    @Override
07    protected ModelAndView handleRequestInternal(HttpServletRequest request,
08 HttpServletResponse response) throws Exception {
09        ModelAndView modelAndView = null;
10        try{
11            modelAndView = super.doResolveException(request, response, handler, ex);
12            //...
13        }catch(Exception ex){
14            String errorTitle = "";
15         
16            if(ex instanceof MyBusinessException){
17                modelAndView = new ModelAndView("businessErrorPage");
18                errorTitle = "A specific title for the MyBusinessException exception";
19                // ... Apply extra business logic: auditing, logging
20                // ...... for the MyBusinessException exception
21 
22            }else if(ex instanceof MyTechnicalException){
23                modelAndView = new ModelAndView("technicalErrorPage");
24                errorTitle = "A specific title for the MyTechnicalException exception";
25                // ... Apply extra business logic: sending emails
26                // ...... for the MyTechnicalException exception
27 
28            }else{
29                modelAndView = new ModelAndView("errorPage");
30                errorTitle = "Error standard exception";
31            }
32 
33            modelAndView.getModelMap().addAttibute("errorTitle", errorTitle );
34            modelAndView.getModelMap().addAttibute("errorMessage", ex.getMessage());       
35        }
36        return modelAndView;
37    }
38}

That’s all!!!!

Huseyin OZVEREN

1 thought on “Java/Spring MVC: Exception Handler, Resolver and Customization”

Leave a Reply to juju Cancel reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.

Related Post