Core server component of Eclipse Jetty web server providing HTTP server functionality, request handling, and connection management
—
The Handler system provides a flexible framework for processing HTTP requests using a chain-of-responsibility pattern. Handlers can wrap, delegate, and transform requests and responses.
The core Handler interface extends request handling with lifecycle and server management.
public interface Handler extends LifeCycle, Destroyable, Request.Handler {
// Server association
Server getServer();
void setServer(Server server);
// Request handling (from Request.Handler)
boolean handle(Request request, Response response, Callback callback) throws Exception;
// Nested interfaces for organization
interface Container extends Handler {
List<Handler> getHandlers();
boolean insertHandler(Handler handler);
boolean removeHandler(Handler handler);
}
interface Collection extends Handler.Container {
// Collection-specific operations
}
interface Singleton extends Handler.Container {
Handler getHandler();
void setHandler(Handler handler);
}
}Abstract base implementation providing common handler functionality.
public abstract class Handler.Abstract extends AbstractLifeCycle implements Handler {
// Server management
public Server getServer();
public void setServer(Server server);
// Template method for request handling
public abstract boolean handle(Request request, Response response, Callback callback)
throws Exception;
// Utility methods
protected boolean isStarted();
protected void doStart() throws Exception;
protected void doStop() throws Exception;
}Wrapper implementation that delegates to a single child handler.
public class Handler.Wrapper extends Handler.AbstractContainer implements Handler.Singleton {
// Child handler management
public Handler getHandler();
public void setHandler(Handler handler);
// Default delegation to child handler
public boolean handle(Request request, Response response, Callback callback) throws Exception {
Handler handler = getHandler();
return handler != null && handler.handle(request, response, callback);
}
}Sequential handler implementation that processes handlers in order.
public class Handler.Sequence extends Handler.AbstractContainer implements Handler.Collection {
// Handler collection management
public List<Handler> getHandlers();
public boolean insertHandler(Handler handler);
public boolean removeHandler(Handler handler);
public void setHandlers(List<Handler> handlers);
// Sequential processing
public boolean handle(Request request, Response response, Callback callback) throws Exception;
}public class HelloWorldHandler extends Handler.Abstract {
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
// Set response headers
response.setStatus(200);
response.getHeaders().put("Content-Type", "text/plain");
// Write response body
String message = "Hello, World! Time: " + Instant.now();
response.write(true, ByteBuffer.wrap(message.getBytes()), callback);
return true; // Request handled
}
}public class RoutingHandler extends Handler.Abstract {
private final Map<String, Handler> routes = new HashMap<>();
public void addRoute(String path, Handler handler) {
routes.put(path, handler);
addBean(handler); // Manage lifecycle
}
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
String path = request.getHttpURI().getPath();
Handler handler = routes.get(path);
if (handler != null) {
return handler.handle(request, response, callback);
}
// No route found
return false;
}
}
// Usage
RoutingHandler router = new RoutingHandler();
router.addRoute("/hello", new HelloWorldHandler());
router.addRoute("/api/status", new StatusHandler());
router.addRoute("/api/users", new UsersHandler());
server.setHandler(router);public class TimingHandler extends Handler.Wrapper {
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
long startTime = System.nanoTime();
// Wrap callback to measure timing
Callback timingCallback = new Callback() {
@Override
public void succeeded() {
long duration = System.nanoTime() - startTime;
response.getHeaders().add("X-Processing-Time-Nanos", String.valueOf(duration));
callback.succeeded();
}
@Override
public void failed(Throwable x) {
long duration = System.nanoTime() - startTime;
System.err.println("Request failed after " + duration + " nanos: " + x.getMessage());
callback.failed(x);
}
};
// Delegate to child handler with timing callback
return super.handle(request, response, timingCallback);
}
}public class FilteredHandler extends Handler.Sequence {
public FilteredHandler() {
// Add handlers in order of execution
addHandler(new AuthenticationHandler());
addHandler(new LoggingHandler());
addHandler(new CompressionHandler());
addHandler(new ApplicationHandler());
}
}
// Authentication filter
public class AuthenticationHandler extends Handler.Abstract {
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
String authHeader = request.getHeaders().get("Authorization");
if (authHeader == null || !isValidAuth(authHeader)) {
response.setStatus(401);
response.getHeaders().put("Content-Type", "text/plain");
response.write(true, ByteBuffer.wrap("Unauthorized".getBytes()), callback);
return true; // Request handled (rejected)
}
return false; // Continue to next handler
}
private boolean isValidAuth(String authHeader) {
// Validate authentication token
return authHeader.startsWith("Bearer ") && authHeader.length() > 20;
}
}public abstract class ConditionalHandler extends Handler.Wrapper {
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
if (shouldHandle(request)) {
return handleConditionally(request, response, callback);
} else {
return super.handle(request, response, callback);
}
}
protected abstract boolean shouldHandle(Request request);
protected boolean handleConditionally(Request request, Response response, Callback callback)
throws Exception {
// Default: delegate to child
return super.handle(request, response, callback);
}
}
// IP-based access control
public class IPRestrictedHandler extends ConditionalHandler {
private final Set<String> allowedIPs;
public IPRestrictedHandler(Set<String> allowedIPs) {
this.allowedIPs = allowedIPs;
}
@Override
protected boolean shouldHandle(Request request) {
String clientIP = request.getConnectionMetaData()
.getRemoteSocketAddress().toString();
return !allowedIPs.contains(clientIP);
}
@Override
protected boolean handleConditionally(Request request, Response response, Callback callback)
throws Exception {
// Reject forbidden IPs
response.setStatus(403);
response.getHeaders().put("Content-Type", "text/plain");
response.write(true, ByteBuffer.wrap("Access Denied".getBytes()), callback);
return true;
}
}public class AsyncProcessingHandler extends Handler.Abstract {
private final ExecutorService executor = Executors.newCachedThreadPool();
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
// Process request asynchronously
CompletableFuture.supplyAsync(() -> {
try {
// Simulate async processing
Thread.sleep(1000);
return processRequest(request);
} catch (Exception e) {
throw new RuntimeException(e);
}
}, executor).thenAccept(result -> {
// Generate response
response.setStatus(200);
response.getHeaders().put("Content-Type", "application/json");
String json = "{\"result\": \"" + result + "\", \"async\": true}";
response.write(true, ByteBuffer.wrap(json.getBytes()), callback);
}).exceptionally(throwable -> {
// Handle error
response.setStatus(500);
response.getHeaders().put("Content-Type", "text/plain");
response.write(true, ByteBuffer.wrap("Processing failed".getBytes()), callback);
return null;
});
return true; // Request handling started
}
private String processRequest(Request request) {
// Simulate complex processing
return "Processed: " + request.getHttpURI().getPath();
}
@Override
protected void doStop() throws Exception {
executor.shutdown();
super.doStop();
}
}public interface Handler.Collection extends Handler.Container {
// Inherited from Container:
List<Handler> getHandlers();
boolean insertHandler(Handler handler);
boolean removeHandler(Handler handler);
// Collection-specific operations
void setHandlers(List<Handler> handlers);
void addHandler(Handler handler);
}public interface Handler.Container extends Handler {
List<Handler> getHandlers();
boolean insertHandler(Handler handler);
boolean removeHandler(Handler handler);
// Descendants and lifecycle management
Handler getDescendant(Class<? extends Handler> type);
<T extends Handler> List<T> getDescendants(Class<T> type);
}public class HandlerTreeExample {
public void exploreHandlerTree(Handler root) {
if (root instanceof Handler.Container) {
Handler.Container container = (Handler.Container) root;
// Get all child handlers
List<Handler> children = container.getHandlers();
// Find specific handler type
Handler errorHandler = container.getDescendant(ErrorHandler.class);
// Find all handlers of specific type
List<StatisticsHandler> statsHandlers =
container.getDescendants(StatisticsHandler.class);
// Process each child
for (Handler child : children) {
System.out.println("Handler: " + child.getClass().getSimpleName());
exploreHandlerTree(child); // Recursive traversal
}
}
}
}public class DynamicHandlerManager {
private final Handler.Sequence mainHandler;
public DynamicHandlerManager() {
this.mainHandler = new Handler.Sequence();
}
public void addMiddleware(Handler middleware) {
// Insert before the last handler (usually the application handler)
List<Handler> handlers = new ArrayList<>(mainHandler.getHandlers());
if (handlers.size() > 0) {
handlers.add(handlers.size() - 1, middleware);
} else {
handlers.add(middleware);
}
mainHandler.setHandlers(handlers);
}
public void removeMiddleware(Class<? extends Handler> middlewareType) {
List<Handler> handlers = new ArrayList<>(mainHandler.getHandlers());
handlers.removeIf(h -> middlewareType.isInstance(h));
mainHandler.setHandlers(handlers);
}
public Handler getRootHandler() {
return mainHandler;
}
}
// Usage
DynamicHandlerManager manager = new DynamicHandlerManager();
manager.addMiddleware(new LoggingHandler());
manager.addMiddleware(new AuthenticationHandler());
manager.addMiddleware(new ApplicationHandler());
server.setHandler(manager.getRootHandler());All handlers participate in the server lifecycle:
public class LifecycleAwareHandler extends Handler.Abstract {
@Override
protected void doStart() throws Exception {
super.doStart();
System.out.println("Handler starting: " + this.getClass().getSimpleName());
// Initialize resources
initializeDatabase();
startBackgroundTasks();
}
@Override
protected void doStop() throws Exception {
System.out.println("Handler stopping: " + this.getClass().getSimpleName());
// Cleanup resources
stopBackgroundTasks();
closeDatabase();
super.doStop();
}
private void initializeDatabase() {
// Setup database connections
}
private void startBackgroundTasks() {
// Start scheduled tasks
}
private void stopBackgroundTasks() {
// Stop scheduled tasks
}
private void closeDatabase() {
// Close database connections
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-eclipse-jetty--jetty-server