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 theexception
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:
- Consistent Error Pages: Create a unified style for error pages to provide a better user experience.
- Avoid Revealing Sensitive Data: Never display stack traces or sensitive information to the user.
- Use Centralized Logging: Implement a centralized mechanism to log and monitor exceptions.
- Handle Specific Errors: Provide user-friendly error messages for known and predictable failures (e.g.,
404 Not Found
,403 Forbidden
). - 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>