CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-eclipse-jetty--jetty-servlet

Eclipse Jetty servlet container providing comprehensive servlet, filter, and listener integration with lifecycle management and dynamic registration support.

Pending
Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Error handling in Eclipse Jetty provides comprehensive error page mapping and custom error response management through the ErrorPageErrorHandler class, supporting HTTP status codes, exception types, and custom error page rendering.

ErrorPageErrorHandler

The ErrorPageErrorHandler extends Jetty's base ErrorHandler to provide servlet-specific error page mapping capabilities.

public class ErrorPageErrorHandler extends ErrorHandler 
        implements ErrorHandler.ErrorPageMapper {
    
    // Constructor
    public ErrorPageErrorHandler();
    
    // Error page mapping
    public String getErrorPage(HttpServletRequest request);
    public void addErrorPage(String pathSpec, String error);
    public void addErrorPage(int code, String error);
    public void addErrorPage(Class<? extends Throwable> exception, String error);
    
    // Error page configuration
    public Map<String, String> getErrorPages();
    public void setErrorPages(Map<String, String> errorPages);
    
    // Error page handling
    protected void handleErrorPage(HttpServletRequest request, Writer writer, 
                                  int code, String message);
}

DefaultServlet Error Support

The DefaultServlet provides built-in error handling for static resource serving.

public class DefaultServlet extends HttpServlet implements ResourceFactory, WelcomeFactory {
    // HTTP method handlers with error responses
    protected void doGet(HttpServletRequest request, HttpServletResponse response);
    protected void doPost(HttpServletRequest request, HttpServletResponse response);
    protected void doPut(HttpServletRequest request, HttpServletResponse response);
    protected void doDelete(HttpServletRequest request, HttpServletResponse response);
    protected void doOptions(HttpServletRequest request, HttpServletResponse response);
    protected void doTrace(HttpServletRequest request, HttpServletResponse response);
    
    // Resource access methods
    public Resource getResource(String pathInContext);
    public String getWelcomeFile(String pathInContext);
    public String getInitParameter(String name);
    public void init();
}

Usage Examples

Basic Error Page Configuration

import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.server.Server;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

// Create error handler and configure error pages
ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();

// Map specific HTTP status codes to error pages
errorHandler.addErrorPage(404, "/error/404.html");
errorHandler.addErrorPage(403, "/error/forbidden.html");
errorHandler.addErrorPage(500, "/error/internal.html");
errorHandler.addErrorPage(503, "/error/unavailable.html");

// Map exception types to error pages
errorHandler.addErrorPage(NullPointerException.class, "/error/npe.html");
errorHandler.addErrorPage(IllegalArgumentException.class, "/error/bad-request.html");
errorHandler.addErrorPage(SQLException.class, "/error/database.html");

// Create context and set error handler
ServletContextHandler context = new ServletContextHandler("/myapp");
context.setErrorHandler(errorHandler);

// Add to server
Server server = new Server(8080);
server.setHandler(context);

Dynamic Error Page Mapping

import java.util.HashMap;
import java.util.Map;

// Create error page mappings programmatically
Map<String, String> errorPages = new HashMap<>();

// HTTP status codes
errorPages.put("404", "/errors/not-found.jsp");
errorPages.put("403", "/errors/access-denied.jsp");
errorPages.put("500", "/errors/server-error.jsp");
errorPages.put("400", "/errors/bad-request.jsp");

// Exception class names
errorPages.put("java.lang.NullPointerException", "/errors/null-pointer.jsp");
errorPages.put("java.lang.IllegalArgumentException", "/errors/illegal-argument.jsp");
errorPages.put("java.sql.SQLException", "/errors/database-error.jsp");
errorPages.put("javax.servlet.ServletException", "/errors/servlet-error.jsp");

// Set all error pages at once
ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
errorHandler.setErrorPages(errorPages);

// Apply to context
context.setErrorHandler(errorHandler);

// Get current error pages for inspection
Map<String, String> currentPages = errorHandler.getErrorPages();
for (Map.Entry<String, String> entry : currentPages.entrySet()) {
    System.out.println("Error " + entry.getKey() + " -> " + entry.getValue());
}

Custom Error Handler Implementation

public class CustomErrorHandler extends ErrorPageErrorHandler {
    
    @Override
    protected void handleErrorPage(HttpServletRequest request, Writer writer, 
                                  int code, String message) {
        try {
            // Get error page for this request
            String errorPage = getErrorPage(request);
            
            if (errorPage != null) {
                // Forward to custom error page
                RequestDispatcher dispatcher = request.getRequestDispatcher(errorPage);
                if (dispatcher != null) {
                    // Set error attributes
                    setErrorAttributes(request, code, message);
                    
                    // Forward to error page
                    dispatcher.forward(request, (HttpServletResponse) writer);
                    return;
                }
            }
            
            // Fallback to default error handling
            generateDefaultErrorPage(writer, code, message);
            
        } catch (Exception e) {
            // Log error and provide minimal response
            System.err.println("Error handling failed: " + e.getMessage());
            generateMinimalErrorPage(writer, code, message);
        }
    }
    
    private void setErrorAttributes(HttpServletRequest request, int code, String message) {
        request.setAttribute("jakarta.servlet.error.status_code", code);
        request.setAttribute("jakarta.servlet.error.message", message);
        request.setAttribute("jakarta.servlet.error.request_uri", request.getRequestURI());
        request.setAttribute("jakarta.servlet.error.servlet_name", request.getServletPath());
        request.setAttribute("jakarta.servlet.error.timestamp", System.currentTimeMillis());
    }
    
    private void generateDefaultErrorPage(Writer writer, int code, String message) {
        try {
            writer.write("<!DOCTYPE html>");
            writer.write("<html><head><title>Error " + code + "</title></head>");
            writer.write("<body>");
            writer.write("<h1>HTTP Error " + code + "</h1>");
            writer.write("<p>" + (message != null ? message : "An error occurred") + "</p>");
            writer.write("</body></html>");
        } catch (IOException e) {
            System.err.println("Failed to write error page: " + e.getMessage());
        }
    }
    
    private void generateMinimalErrorPage(Writer writer, int code, String message) {
        try {
            writer.write("Error " + code + ": " + (message != null ? message : "Internal Error"));
        } catch (IOException e) {
            // Cannot write response - log only
            System.err.println("Cannot write error response: " + e.getMessage());
        }
    }
}

// Use custom error handler
CustomErrorHandler customHandler = new CustomErrorHandler();
customHandler.addErrorPage(500, "/errors/custom-500.jsp");
customHandler.addErrorPage(404, "/errors/custom-404.jsp");

context.setErrorHandler(customHandler);

Error Servlet Implementation

import jakarta.servlet.ServletException;
import java.io.IOException;
import java.io.PrintWriter;

public class ErrorDisplayServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        // Get error attributes set by container
        Integer statusCode = (Integer) request.getAttribute("jakarta.servlet.error.status_code");
        String message = (String) request.getAttribute("jakarta.servlet.error.message");
        String requestUri = (String) request.getAttribute("jakarta.servlet.error.request_uri");
        String servletName = (String) request.getAttribute("jakarta.servlet.error.servlet_name");
        Throwable exception = (Throwable) request.getAttribute("jakarta.servlet.error.exception");
        Class<?> exceptionType = (Class<?>) request.getAttribute("jakarta.servlet.error.exception_type");
        
        // Set response content type
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        
        // Generate error page
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Application Error</title>");
        out.println("<style>");
        out.println("body { font-family: Arial, sans-serif; margin: 40px; }");
        out.println(".error { color: #d32f2f; }");
        out.println(".details { background: #f5f5f5; padding: 20px; margin: 20px 0; }");
        out.println("</style>");
        out.println("</head>");
        out.println("<body>");
        
        out.println("<h1 class=\"error\">Application Error</h1>");
        
        if (statusCode != null) {
            out.println("<h2>HTTP Status: " + statusCode + "</h2>");
        }
        
        if (message != null) {
            out.println("<p><strong>Message:</strong> " + escapeHtml(message) + "</p>");
        }
        
        if (requestUri != null) {
            out.println("<p><strong>Request URI:</strong> " + escapeHtml(requestUri) + "</p>");
        }
        
        if (servletName != null) {
            out.println("<p><strong>Servlet:</strong> " + escapeHtml(servletName) + "</p>");
        }
        
        if (exception != null) {
            out.println("<div class=\"details\">");
            out.println("<h3>Exception Details</h3>");
            out.println("<p><strong>Type:</strong> " + exception.getClass().getName() + "</p>");
            out.println("<p><strong>Message:</strong> " + escapeHtml(exception.getMessage()) + "</p>");
            
            // Optional: Include stack trace in development
            if (isDevelopmentMode()) {
                out.println("<h4>Stack Trace</h4>");
                out.println("<pre>");
                exception.printStackTrace(out);
                out.println("</pre>");
            }
            out.println("</div>");
        }
        
        out.println("<p><a href=\"/\">Return to Home</a></p>");
        out.println("</body>");
        out.println("</html>");
    }
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        doGet(request, response);
    }
    
    private String escapeHtml(String text) {
        if (text == null) return "";
        return text.replace("&", "&amp;")
                  .replace("<", "&lt;")
                  .replace(">", "&gt;")
                  .replace("\"", "&quot;")
                  .replace("'", "&#x27;");
    }
    
    private boolean isDevelopmentMode() {
        // Check system property or configuration
        return "development".equals(System.getProperty("app.mode"));
    }
}

// Register error display servlet
context.addServlet(ErrorDisplayServlet.class, "/error-display");

// Map error codes to error servlet
ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
errorHandler.addErrorPage(500, "/error-display");
errorHandler.addErrorPage(404, "/error-display");
errorHandler.addErrorPage(403, "/error-display");

context.setErrorHandler(errorHandler);

Exception-Specific Error Handling

// Custom exceptions for different error scenarios
public class BusinessLogicException extends Exception {
    public BusinessLogicException(String message) {
        super(message);
    }
}

public class DataAccessException extends RuntimeException {
    public DataAccessException(String message, Throwable cause) {
        super(message, cause);
    }
}

public class ValidationException extends Exception {
    private final Map<String, String> fieldErrors;
    
    public ValidationException(Map<String, String> fieldErrors) {
        super("Validation failed");
        this.fieldErrors = fieldErrors;
    }
    
    public Map<String, String> getFieldErrors() {
        return fieldErrors;
    }
}

// Configure exception-specific error pages
ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();

// Business logic errors
errorHandler.addErrorPage(BusinessLogicException.class, "/errors/business-error.jsp");

// Data access errors
errorHandler.addErrorPage(DataAccessException.class, "/errors/data-error.jsp");

// Validation errors
errorHandler.addErrorPage(ValidationException.class, "/errors/validation-error.jsp");

// Runtime exceptions
errorHandler.addErrorPage(RuntimeException.class, "/errors/runtime-error.jsp");

// Servlet exceptions
errorHandler.addErrorPage(ServletException.class, "/errors/servlet-error.jsp");

context.setErrorHandler(errorHandler);

Error Filtering and Logging

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.DispatcherType;
import java.util.EnumSet;

public class ErrorLoggingFilter implements Filter {
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // Initialize logging configuration
    }
    
    @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);
        } catch (Exception e) {
            // Log error with context information
            logError(httpRequest, e);
            
            // Set error attributes for error page
            request.setAttribute("jakarta.servlet.error.exception", e);
            request.setAttribute("jakarta.servlet.error.exception_type", e.getClass());
            request.setAttribute("jakarta.servlet.error.message", e.getMessage());
            request.setAttribute("jakarta.servlet.error.request_uri", httpRequest.getRequestURI());
            
            // Re-throw to let error handler process
            throw e;
        }
        
        // Check for error status codes
        int status = httpResponse.getStatus();
        if (status >= 400) {
            logHttpError(httpRequest, status);
        }
    }
    
    private void logError(HttpServletRequest request, Exception e) {
        System.err.println("ERROR: " + e.getClass().getSimpleName() + 
                          " at " + request.getRequestURI());
        System.err.println("Message: " + e.getMessage());
        System.err.println("User-Agent: " + request.getHeader("User-Agent"));
        System.err.println("Remote Addr: " + request.getRemoteAddr());
        e.printStackTrace();
    }
    
    private void logHttpError(HttpServletRequest request, int status) {
        System.err.println("HTTP ERROR " + status + ": " + request.getRequestURI());
        System.err.println("Method: " + request.getMethod());
        System.err.println("Query: " + request.getQueryString());
    }
    
    @Override
    public void destroy() {
        // Cleanup logging resources
    }
}

// Register error logging filter for all request types including ERROR
FilterHolder errorFilter = new FilterHolder(ErrorLoggingFilter.class);
context.addFilter(errorFilter, "/*", EnumSet.of(
    DispatcherType.REQUEST,
    DispatcherType.ERROR,
    DispatcherType.FORWARD
));

Error Page Templates with JSP

<!-- /errors/500.jsp -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isErrorPage="true" %>
<!DOCTYPE html>
<html>
<head>
    <title>Internal Server Error</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .error-container { max-width: 800px; margin: 0 auto; }
        .error-header { color: #d32f2f; border-bottom: 2px solid #d32f2f; }
        .error-details { background: #f5f5f5; padding: 20px; margin: 20px 0; }
        pre { background: #fff; padding: 10px; border: 1px solid #ddd; overflow-x: auto; }
    </style>
</head>
<body>
    <div class="error-container">
        <h1 class="error-header">Internal Server Error (500)</h1>
        
        <p>We're sorry, but something went wrong on our end. Please try again later.</p>
        
        <div class="error-details">
            <h3>Error Information</h3>
            <p><strong>Request ID:</strong> <%= request.getAttribute("requestId") %></p>
            <p><strong>Timestamp:</strong> <%= new java.util.Date() %></p>
            <p><strong>Request URI:</strong> <%= request.getAttribute("jakarta.servlet.error.request_uri") %></p>
            
            <%
            Throwable exception = (Throwable) request.getAttribute("jakarta.servlet.error.exception");
            if (exception != null && "development".equals(System.getProperty("app.mode"))) {
            %>
                <h4>Exception Details (Development Mode)</h4>
                <p><strong>Type:</strong> <%= exception.getClass().getName() %></p>
                <p><strong>Message:</strong> <%= exception.getMessage() %></p>
                
                <h4>Stack Trace</h4>
                <pre>
                <%
                java.io.StringWriter sw = new java.io.StringWriter();
                java.io.PrintWriter pw = new java.io.PrintWriter(sw);
                exception.printStackTrace(pw);
                out.print(sw.toString());
                %>
                </pre>
            <% } %>
        </div>
        
        <p><a href="${pageContext.request.contextPath}/">Return to Home</a></p>
    </div>
</body>
</html>

Complete Error Handling Setup

// Comprehensive error handling configuration
public class ErrorHandlingConfiguration {
    
    public static void configureErrorHandling(ServletContextHandler context) {
        // Create custom error handler
        ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
        
        // Configure HTTP status error pages
        configureHttpErrors(errorHandler);
        
        // Configure exception error pages
        configureExceptionErrors(errorHandler);
        
        // Set error handler on context
        context.setErrorHandler(errorHandler);
        
        // Add error logging filter
        addErrorLoggingFilter(context);
        
        // Add error display servlets
        addErrorServlets(context);
    }
    
    private static void configureHttpErrors(ErrorPageErrorHandler errorHandler) {
        errorHandler.addErrorPage(400, "/error/400.jsp");
        errorHandler.addErrorPage(401, "/error/401.jsp");
        errorHandler.addErrorPage(403, "/error/403.jsp");
        errorHandler.addErrorPage(404, "/error/404.jsp");
        errorHandler.addErrorPage(405, "/error/405.jsp");
        errorHandler.addErrorPage(500, "/error/500.jsp");
        errorHandler.addErrorPage(502, "/error/502.jsp");
        errorHandler.addErrorPage(503, "/error/503.jsp");
    }
    
    private static void configureExceptionErrors(ErrorPageErrorHandler errorHandler) {
        // Application exceptions
        errorHandler.addErrorPage(BusinessLogicException.class, "/error/business.jsp");
        errorHandler.addErrorPage(ValidationException.class, "/error/validation.jsp");
        errorHandler.addErrorPage(DataAccessException.class, "/error/database.jsp");
        
        // Standard exceptions
        errorHandler.addErrorPage(NullPointerException.class, "/error/npe.jsp");
        errorHandler.addErrorPage(IllegalArgumentException.class, "/error/bad-argument.jsp");
        errorHandler.addErrorPage(ServletException.class, "/error/servlet.jsp");
        
        // Security exceptions
        errorHandler.addErrorPage(SecurityException.class, "/error/security.jsp");
    }
    
    private static void addErrorLoggingFilter(ServletContextHandler context) {
        FilterHolder loggingFilter = new FilterHolder(ErrorLoggingFilter.class);
        context.addFilter(loggingFilter, "/*", EnumSet.of(
            DispatcherType.REQUEST,
            DispatcherType.ERROR,
            DispatcherType.FORWARD,
            DispatcherType.INCLUDE
        ));
    }
    
    private static void addErrorServlets(ServletContextHandler context) {
        // Error display servlet
        context.addServlet(ErrorDisplayServlet.class, "/error/*");
        
        // API error servlet for JSON responses
        context.addServlet(ApiErrorServlet.class, "/api/error/*");
    }
}

// Usage
ServletContextHandler context = new ServletContextHandler("/myapp");
ErrorHandlingConfiguration.configureErrorHandling(context);

Install with Tessl CLI

npx tessl i tessl/maven-org-eclipse-jetty--jetty-servlet

docs

error-handling.md

filter-handling.md

index.md

listeners.md

monitoring.md

servlet-context.md

servlet-handling.md

testing.md

tile.json