How to handle exceptions thrown by another servlet in an application?
sobes.tech AI
Answer from AI
In the standard servlet architecture, exceptions thrown by one servlet cannot be directly handled by another servlet within the current request. Each request is processed by a separate thread associated with the lifecycle of a single servlet.
However, similar behavior can be achieved using the following approaches:
-
Using the servlet container's error handling mechanism:
- In
web.xml, you can configure error pages for specific exception types or HTTP status codes. The servlet container (e.g., Tomcat, Jetty) will redirect to this page when an exception occurs. - On the error page (which can be another servlet or JSP), you can retrieve exception information from request attributes.
- Attributes are accessible via
request.getAttribute(). Keys includejavax.servlet.error.exception,javax.servlet.error.exception_type,javax.servlet.error.message,javax.servlet.error.request_uri.
<error-page> <exception-type>java.lang.RuntimeException</exception-type> <location>/errorServlet</location> </error-page> <error-page> <error-code>500</error-code> <location>/errorServlet</location> </error-page>// ErrorServlet.java import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/errorServlet") public class ErrorServlet extends HttpServlet { @Override protected void doGet(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"); String requestUri = (String) request.getAttribute("javax.servlet.error.request_uri"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html><body>"); out.println("<h2>Error!</h2>"); out.println("<p>Status code: " + statusCode + "</p>"); out.println("<p>Servlet: " + (servletName != null ? servletName : "Unknown") + "</p>"); out.println("<p>Request URI: " + (requestUri != null ? requestUri : "Unknown") + "</p>"); if (throwable != null) { out.println("<p>Exception type: " + throwable.getClass().getName() + "</p>"); out.println("<p>Message: " + throwable.getMessage() + "</p>"); // Stack trace can also be printed for debugging // throwable.printStackTrace(out); } out.println("</body></html>"); } } - In
-
Using servlet filters:
- A filter can wrap the
doFilterchain in a try-catch block. - If a servlet in the chain throws an exception, the filter catches it.
- Inside the catch block, the filter can either handle the exception itself or forward the request to a dedicated error handler (possibly another servlet) using
request.getRequestDispatcher("/errorServlet").forward(request, response).
// ExceptionHandlingFilter.java import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebFilter("/*") // Applies to all requests public class ExceptionHandlingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // Filter initialization } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; try { chain.doFilter(request, response); // Pass request further down the chain (to servlet or next filter) } catch (Exception e) { // Catch exception thrown by servlet or next filter System.err.println("Error occurred during request processing for URI: " + httpRequest.getRequestURI()); e.printStackTrace(); // Log the error // Save error info for handler httpRequest.setAttribute("javax.servlet.error.exception", e); httpRequest.setAttribute("javax.servlet.error.message", e.getMessage()); httpRequest.setAttribute("javax.servlet.error.request_uri", httpRequest.getRequestURI()); // Optionally set status code httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500 Internal Server Error // Forward to error handling servlet httpRequest.getRequestDispatcher("/errorServlet").forward(httpRequest, httpResponse); } } @Override public void destroy() { // Cleanup resources } } - A filter can wrap the
These two approaches allow centralized error handling and prevent default container error messages from being shown to the user. The first method (via web.xml) is simpler for basic status code and exception type handling. The second method (via filter) offers more flexibility, allowing additional logic (e.g., logging) before forwarding or handling.