diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ErrorPageErrorHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ErrorPageErrorHandler.java index b5788f1b6a72..54ba33c1f307 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ErrorPageErrorHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ErrorPageErrorHandler.java @@ -98,7 +98,7 @@ public String getErrorPage(HttpServletRequest request) if (error instanceof ServletException && _unwrapServletException) { - Throwable unwrapped = ((ServletException)error).getRootCause(); + Throwable unwrapped = getFirstNonServletException(error); if (unwrapped != null) { request.setAttribute(Dispatcher.ERROR_EXCEPTION, unwrapped); @@ -177,6 +177,20 @@ public String getErrorPage(HttpServletRequest request) return errorPage; } + /** + * + * @param t the initial exception + * @return the first non {@link ServletException} from root cause chain + */ + private Throwable getFirstNonServletException(Throwable t) + { + if (t instanceof ServletException && t.getCause() != null) + { + return getFirstNonServletException(t.getCause()); + } + return t; + } + public Map getErrorPages() { return _errorPages; diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ErrorPageTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ErrorPageTest.java index e1545c41284f..2f44ea99e442 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ErrorPageTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ErrorPageTest.java @@ -89,6 +89,7 @@ public void init() throws Exception _context.addFilter(SingleDispatchFilter.class, "/*", EnumSet.allOf(DispatcherType.class)); _context.addServlet(DefaultServlet.class, "/"); _context.addServlet(FailServlet.class, "/fail/*"); + _context.addServlet(FailServletDoubleWrap.class, "/fail-double-wrap/*"); _context.addServlet(FailClosedServlet.class, "/fail-closed/*"); _context.addServlet(ErrorServlet.class, "/error/*"); _context.addServlet(AppServlet.class, "/app/*"); @@ -307,6 +308,14 @@ public void testErrorException() throws Exception assertThat(response, Matchers.containsString("ERROR_EXCEPTION_TYPE: class jakarta.servlet.ServletException")); assertThat(response, Matchers.containsString("ERROR_SERVLET: org.eclipse.jetty.servlet.ErrorPageTest$FailServlet-")); assertThat(response, Matchers.containsString("ERROR_REQUEST_URI: /fail/exception")); + response = _connector.getResponse("GET /fail-double-wrap/exception HTTP/1.0\r\n\r\n"); + assertThat(response, Matchers.containsString("HTTP/1.1 500 Server Error")); + assertThat(response, Matchers.containsString("ERROR_PAGE: /TestException")); + assertThat(response, Matchers.containsString("ERROR_CODE: 500")); + assertThat(response, Matchers.containsString("ERROR_EXCEPTION: jakarta.servlet.ServletException: jakarta.servlet.ServletException: java.lang.IllegalStateException: Test Exception")); + assertThat(response, Matchers.containsString("ERROR_EXCEPTION_TYPE: class jakarta.servlet.ServletException")); + assertThat(response, Matchers.containsString("ERROR_SERVLET: org.eclipse.jetty.servlet.ErrorPageTest$FailServletDoubleWrap-")); + assertThat(response, Matchers.containsString("ERROR_REQUEST_URI: /fail-double-wrap/exception")); } _errorPageErrorHandler.setUnwrapServletException(true); @@ -320,6 +329,14 @@ public void testErrorException() throws Exception assertThat(response, Matchers.containsString("ERROR_EXCEPTION_TYPE: class java.lang.IllegalStateException")); assertThat(response, Matchers.containsString("ERROR_SERVLET: org.eclipse.jetty.servlet.ErrorPageTest$FailServlet-")); assertThat(response, Matchers.containsString("ERROR_REQUEST_URI: /fail/exception")); + response = _connector.getResponse("GET /fail-double-wrap/exception HTTP/1.0\r\n\r\n"); + assertThat(response, Matchers.containsString("HTTP/1.1 500 Server Error")); + assertThat(response, Matchers.containsString("ERROR_PAGE: /TestException")); + assertThat(response, Matchers.containsString("ERROR_CODE: 500")); + assertThat(response, Matchers.containsString("ERROR_EXCEPTION: java.lang.IllegalStateException: Test Exception")); + assertThat(response, Matchers.containsString("ERROR_EXCEPTION_TYPE: class java.lang.IllegalStateException")); + assertThat(response, Matchers.containsString("ERROR_SERVLET: org.eclipse.jetty.servlet.ErrorPageTest$FailServletDoubleWrap-")); + assertThat(response, Matchers.containsString("ERROR_REQUEST_URI: /fail-double-wrap/exception")); } } @@ -637,6 +654,19 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t } } + public static class FailServletDoubleWrap extends HttpServlet implements Servlet + { + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + String code = request.getParameter("code"); + if (code != null) + response.sendError(Integer.parseInt(code)); + else + throw new ServletException(new ServletException(new IllegalStateException("Test Exception"))); + } + } + public static class FailClosedServlet extends HttpServlet implements Servlet { @Override