Global Exception configuration using web.xml, servlet and jsp

Introduction

This tutorial will show how you can configure global exception/error handling using deployment descriptor, servlet and jsp in your web applications. The aim of this tutorial is to teach whenever an exception or error occurs in an web based application, then that exception or error would be thrown in an appropriate manner. The error page is finally shown to the end users with the exception or error information in jsp page.

For this you do not need to create as many jsp pages or servlets as many exceptions occur rather you will create just one servlet for capturing exceptions or errors and only one jsp page for displaying error information to the end users.

You need to put necessary configurations for the exceptions in web.xml file.

You can provide link to the application home page or some details about the error information to let user know what went wrong in the application. But to keep things simple we won’t have such link to provide more details on errors.

Related Posts:

Prerequisites

  • Knowledge of Java, JSP and Servlet (3.0.1 to 4.0.1)
  • Required dependencies in pom.xml file

Project Setup

Create a maven based web application in Eclipse with the following details:

Group Id: com.roytuts
Artifact Id: web-app-global-exceptions

Once you create maven based web project in Eclipse then update your pom.xml file to match the below file:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.roytuts</groupId>
	<artifactId>web-app-global-exceptions</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>12</maven.compiler.source>
		<maven.compiler.target>12</maven.compiler.target>
	</properties>

	<dependencies>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.0.1 to 4.0.1</version>
			<scope>provided</scope>
		</dependency>

	</dependencies>

	<build>
		<finalName>web-app-global-exceptions</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
			</plugin>
		</plugins>
	</build>
</project>

In the above build file I have added only one dependency with provided scope because servlet & jsp APIs are available in the Tomcat or any Java based web server.

JSP Pages

The index.jsp page is nothing but shows welcome page with simple message about the application:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!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=ISO-8859-1">
<title>Web Application Global Exception</title>
</head>
<body>
	<div>Servlet Exception example</div>
</body>
</html>

The below error/error.jsp page will be rendered when you are accessing a URL, which is not found or which is not allowed to access etc.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1" isErrorPage="true"%>
<!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=ISO-8859-1">
<title>Web Application Global exception - error page</title>
</head>
<body>
	<p>${errorMsg}</p>
</body>
</html>

Servlet for Error Handling

You can have multiple servlets depending upon the type of exceptions or errors in your application but for simplicity I will create only one servlet and use it for both exceptions and errors.

Below is the ErrorPageHandler servlet’s source code:

package com.roytuts.web.app.global.exceptions;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/ErrorPageHandler")
public class ErrorPageHandler extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public ErrorPageHandler() {
		super();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		cathException(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		cathException(request, response);
	}

	private void cathException(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");
		Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");

		String servletName = (String) request.getAttribute("javax.servlet.error.servlet_name");

		if (servletName == null) {
			servletName = "Unknown Path Segment";
		}

		String requestUri = (String) request.getAttribute("javax.servlet.error.request_uri");
		if (requestUri == null) {
			requestUri = "Unknown Request URI";
		}

		StringBuilder sb = new StringBuilder();

		if (throwable == null && statusCode == null) {
			sb.append("Error information is missing").append("<br/>").append("Please return to the Home Page");
		} else if (statusCode != null) {
			sb.append("Status Code: ").append(statusCode).append("</br/>")
					.append("For more information on status code please go to Status Code Definitions");
		} else {
			sb.append("Error information").append("<br/>").append("Servlet Name : ").append(servletName)
					.append("Exception Type : ").append(throwable.getClass().getName()).append("The request URI: ")
					.append(requestUri).append("<br/>").append("The exception message: ")
					.append(throwable.getMessage());
		}

		request.setAttribute("errorMsg", sb.toString());

		RequestDispatcher requestDispatcher = request.getRequestDispatcher("/error/error.jsp");
		requestDispatcher.forward(request, response);
	}

}

In the above servlet class, most of the things are self-explanatory.

When exception or error scenario occurs, servlet container will invoke the corresponding HTTP method of the ErrorPageHandler servlet and pass the request and response object.

Here I have provided implementation for both doGet() and doPost() methods using a common method cathException() to handle the exceptions or errors in both methods.

Before servlet container invokes the servlet to handle the exception, it sets some attributes in the request to get useful information about the exception, some of them are javax.servlet.error.exception, javax.servlet.error.status_code, javax.servlet.error.servlet_name and javax.servlet.error.request_uri.

I have used @WebServlet annotation to map the URL pattern. You can also remove this annotation and add an entry to the web.xml file. You can check how to configure it (commented code) in the web.xml file.

Deployment Descriptor – web.xml

Let’s configure the deployment descriptor file. This deployment descriptor was tested with XSD version 3.0, 3.1 and 4.0.

<?xml version="1.0" encoding="UTF-8"?>

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

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
	
<!--<web-app metadata-complete="false"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
	version="4.0">-->

	<display-name>Web Application Global Exceptions</display-name>

	<error-page>
		<!-- Missing login -->
		<error-code>401</error-code>
		<location>/error/eror.jsp</location>
	</error-page>

	<error-page>
		<!-- Forbidden directory listing -->
		<error-code>403</error-code>
		<location>/ErrorPageHandler</location>
	</error-page>

	<error-page>
		<!-- Missing resource -->
		<error-code>404</error-code>
		<location>/ErrorPageHandler</location>
	</error-page>

	<error-page>
		<!-- Uncaught exception -->
		<error-code>500</error-code>
		<location>/ErrorPageHandler</location>
	</error-page>

	<error-page>
		<!-- Unsupported servlet method -->
		<error-code>503</error-code>
		<location>/ErrorPageHandler</location>
	</error-page>

	<!-- exception-type related error pages -->
	<error-page>
		<exception-type>java.lang.Throwable</exception-type>
		<location>/ErrorPageHandler</location>
	</error-page>
	
	<!-- <servlet>
        <servlet-name>ErrorPageServlet</servlet-name>
        <servlet-class>com.roytuts.web.app.global.exceptions.ErrorPageHandler</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>ErrorPageServlet</servlet-name>
        <url-pattern>/ErrorPageHandler</url-pattern>
    </servlet-mapping> -->

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

As you can see in the above source code, it’s very easy to specify ErrorPageHandler servlet for the application using error-page element. Each error-page element should have either error-code or exception-type element. I defined the ErrorPageHandler servlet in location element.

<error-page>
	<!-- Missing login -->
	<error-code>401</error-code>
	<location>/error/eror.jsp</location>
</error-page>

<error-page>
	<!-- Forbidden directory listing -->
	<error-code>403</error-code>
	<location>/ErrorPageHandler</location>
</error-page>

<error-page>
	<!-- Missing resource -->
	<error-code>404</error-code>
	<location>/ErrorPageHandler</location>
</error-page>

<error-page>
	<!-- Uncaught exception -->
	<error-code>500</error-code>
	<location>/ErrorPageHandler</location>
</error-page>

<error-page>
	<!-- Unsupported servlet method -->
	<error-code>503</error-code>
	<location>/ErrorPageHandler</location>
</error-page>

Based on above configuration, if the application throws 404 error, 403 error, 500 error, or any kind of exception then it will be handled by ErrorPageHandler servlet.

You can also configure different error page for different exception type but I have used.

<error-page>
	<exception-type>java.lang.Throwable</exception-type>
	<location>/ErrorPageHandler</location>
</error-page>

for all kind of exception handling in one line.

Now when you hit servlet or any URL that is throwing Exception, you get a response like the below:

global exception configuration using web.xml servlet and jsp

If page is not found then you will get the following error:

global exception configuration using web.xml servlet and jsp

Source Code

Download

Leave a Reply

Your email address will not be published. Required fields are marked *