How do I handle exceptions and errors in Jakarta Servlets?

Handling exceptions and errors in Jakarta Servlets involves several approaches, ranging from defining error-handling configurations in the deployment descriptor (web.xml) to using annotations and specific coding practices. Below are the typical ways to handle errors and exceptions in Jakarta Servlets:


1. Using web.xml for Declarative Exception Handling

In the web.xml file, you can define error pages that are mapped to specific exceptions or HTTP status codes. When an error or exception occurs, the corresponding error page is displayed.

Example:

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
         version="6.0">
    <!-- Define an error page for a specific HTTP status code -->
    <error-page>
        <error-code>404</error-code>
        <location>/error-404.jsp</location>
    </error-page>

    <!-- Define an error page for a specific exception -->
    <error-page>
        <exception-type>java.lang.Exception</exception-type>
        <location>/error-exception.jsp</location>
    </error-page>
</web-app>
  • error-code: Maps a specific HTTP status code (e.g., 404) to an error page.
  • exception-type: Maps a specific Java exception to an error page.
  • location: Specifies the location of the JSP or HTML page to display.

2. Using @WebServlet and Exception Handling in Code

In your custom servlet, you can explicitly handle exceptions using try-catch blocks or override the service or doGet/doPost methods.

Example:

package org.kodejava.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet(urlPatterns = "/exceptionServlet", asyncSupported = true)
public class ExceptionServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            // Servlet logic that may throw an exception
            int result = 10 / 0;  // This will throw an ArithmeticException
        } catch (ArithmeticException e) {
            // Handle specific exceptions
            request.setAttribute("errorMessage", "An error occurred: " + e.getMessage());
            request.getRequestDispatcher("/error.jsp").forward(request, response);
        } catch (Exception e) {
            // Handle generic exceptions
            throw new ServletException("An unexpected error occurred", e);
        }
    }
}

3. Custom Error Pages in JSP

Error pages can be written as JSPs (.jsp). To make use of the exception details, JSPs have access to the exception and other implicit objects such as request and response.

Example: error-exception.jsp

<%@ page isErrorPage="true" %>
<html>
<head><title>Error Page</title></head>
<body>
    <h1>An error occurred</h1>
    <p>Error message: ${exception.message}</p>
    <p>Exception type: ${exception.class.name}</p>
</body>
</html>
  • The attribute isErrorPage="true" makes the JSP aware of the exception object.

4. Defining an Error Filter

You can define a Jakarta Servlet filter that intercepts all requests and handles errors more generically before they reach the targeted servlet or after they are processed.

Example:

package org.kodejava.servlet;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;

import java.io.IOException;

@WebFilter("/*")
public class ErrorHandlingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        try {
            chain.doFilter(request, response); // Pass request and response to the next filter or servlet
        } catch (Exception e) {
            request.setAttribute("errorMessage", e.getMessage());
            request.getRequestDispatcher("/error.jsp").forward(request, response);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }
}

This filter catches any unhandled exceptions and forwards the request to an error page.


5. Logging Exceptions

It is a best practice to log exceptions for debugging and monitoring purposes. You can use logging frameworks like Java’s java.util.logging, Log4j, or SLF4J to capture exceptions.

Example with java.util.logging:

package org.kodejava.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.logging.Logger;

@WebServlet(urlPatterns = "/loggingServlet", asyncSupported = true)
public class LoggingServlet extends HttpServlet {
    private static final Logger logger = Logger.getLogger(LoggingServlet.class.getName());

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            // Code that might throw exceptions
        } catch (Exception e) {
            logger.severe("An unexpected error occurred: " + e.getMessage());
            throw new ServletException("Internal server error", e);
        }
    }
}

6. Using HTTP Status Codes

Always set appropriate HTTP status codes when handling errors, so clients are aware of the issue.

Example:

response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid input provided");

Best Practices:

  1. Consistent Error Pages: Create a unified style for error pages to provide a better user experience.
  2. Avoid Revealing Sensitive Data: Never display stack traces or sensitive information to the user.
  3. Use Centralized Logging: Implement a centralized mechanism to log and monitor exceptions.
  4. Handle Specific Errors: Provide user-friendly error messages for known and predictable failures (e.g., 404 Not Found, 403 Forbidden).
  5. Fallback Handling: Ensure a fallback mechanism is in place for uncaught exceptions (e.g., generic error page).

By combining these mechanisms, you can effectively handle exceptions and errors in Jakarta Servlets while ensuring robust error handling and user-friendly responses.


Maven dependencies

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.1.0</version>
    <scope>provided</scope>
</dependency>

Maven Central

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.