0
# Handler System
1
2
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.
3
4
## Handler Interface
5
6
The core `Handler` interface extends request handling with lifecycle and server management.
7
8
```java { .api }
9
public interface Handler extends LifeCycle, Destroyable, Request.Handler {
10
// Server association
11
Server getServer();
12
void setServer(Server server);
13
14
// Request handling (from Request.Handler)
15
boolean handle(Request request, Response response, Callback callback) throws Exception;
16
17
// Nested interfaces for organization
18
interface Container extends Handler {
19
List<Handler> getHandlers();
20
boolean insertHandler(Handler handler);
21
boolean removeHandler(Handler handler);
22
}
23
24
interface Collection extends Handler.Container {
25
// Collection-specific operations
26
}
27
28
interface Singleton extends Handler.Container {
29
Handler getHandler();
30
void setHandler(Handler handler);
31
}
32
}
33
```
34
35
## Base Handler Classes
36
37
### Handler.Abstract
38
39
Abstract base implementation providing common handler functionality.
40
41
```java { .api }
42
public abstract class Handler.Abstract extends AbstractLifeCycle implements Handler {
43
// Server management
44
public Server getServer();
45
public void setServer(Server server);
46
47
// Template method for request handling
48
public abstract boolean handle(Request request, Response response, Callback callback)
49
throws Exception;
50
51
// Utility methods
52
protected boolean isStarted();
53
protected void doStart() throws Exception;
54
protected void doStop() throws Exception;
55
}
56
```
57
58
### Handler.Wrapper
59
60
Wrapper implementation that delegates to a single child handler.
61
62
```java { .api }
63
public class Handler.Wrapper extends Handler.AbstractContainer implements Handler.Singleton {
64
// Child handler management
65
public Handler getHandler();
66
public void setHandler(Handler handler);
67
68
// Default delegation to child handler
69
public boolean handle(Request request, Response response, Callback callback) throws Exception {
70
Handler handler = getHandler();
71
return handler != null && handler.handle(request, response, callback);
72
}
73
}
74
```
75
76
### Handler.Sequence
77
78
Sequential handler implementation that processes handlers in order.
79
80
```java { .api }
81
public class Handler.Sequence extends Handler.AbstractContainer implements Handler.Collection {
82
// Handler collection management
83
public List<Handler> getHandlers();
84
public boolean insertHandler(Handler handler);
85
public boolean removeHandler(Handler handler);
86
public void setHandlers(List<Handler> handlers);
87
88
// Sequential processing
89
public boolean handle(Request request, Response response, Callback callback) throws Exception;
90
}
91
```
92
93
## Usage Examples
94
95
### Simple Handler Implementation
96
97
```java
98
public class HelloWorldHandler extends Handler.Abstract {
99
@Override
100
public boolean handle(Request request, Response response, Callback callback)
101
throws Exception {
102
103
// Set response headers
104
response.setStatus(200);
105
response.getHeaders().put("Content-Type", "text/plain");
106
107
// Write response body
108
String message = "Hello, World! Time: " + Instant.now();
109
response.write(true, ByteBuffer.wrap(message.getBytes()), callback);
110
111
return true; // Request handled
112
}
113
}
114
```
115
116
### Path-Based Routing Handler
117
118
```java
119
public class RoutingHandler extends Handler.Abstract {
120
private final Map<String, Handler> routes = new HashMap<>();
121
122
public void addRoute(String path, Handler handler) {
123
routes.put(path, handler);
124
addBean(handler); // Manage lifecycle
125
}
126
127
@Override
128
public boolean handle(Request request, Response response, Callback callback)
129
throws Exception {
130
131
String path = request.getHttpURI().getPath();
132
Handler handler = routes.get(path);
133
134
if (handler != null) {
135
return handler.handle(request, response, callback);
136
}
137
138
// No route found
139
return false;
140
}
141
}
142
143
// Usage
144
RoutingHandler router = new RoutingHandler();
145
router.addRoute("/hello", new HelloWorldHandler());
146
router.addRoute("/api/status", new StatusHandler());
147
router.addRoute("/api/users", new UsersHandler());
148
149
server.setHandler(router);
150
```
151
152
### Wrapper Handler with Request/Response Modification
153
154
```java
155
public class TimingHandler extends Handler.Wrapper {
156
157
@Override
158
public boolean handle(Request request, Response response, Callback callback)
159
throws Exception {
160
161
long startTime = System.nanoTime();
162
163
// Wrap callback to measure timing
164
Callback timingCallback = new Callback() {
165
@Override
166
public void succeeded() {
167
long duration = System.nanoTime() - startTime;
168
response.getHeaders().add("X-Processing-Time-Nanos", String.valueOf(duration));
169
callback.succeeded();
170
}
171
172
@Override
173
public void failed(Throwable x) {
174
long duration = System.nanoTime() - startTime;
175
System.err.println("Request failed after " + duration + " nanos: " + x.getMessage());
176
callback.failed(x);
177
}
178
};
179
180
// Delegate to child handler with timing callback
181
return super.handle(request, response, timingCallback);
182
}
183
}
184
```
185
186
### Sequential Handler Processing
187
188
```java
189
public class FilteredHandler extends Handler.Sequence {
190
191
public FilteredHandler() {
192
// Add handlers in order of execution
193
addHandler(new AuthenticationHandler());
194
addHandler(new LoggingHandler());
195
addHandler(new CompressionHandler());
196
addHandler(new ApplicationHandler());
197
}
198
}
199
200
// Authentication filter
201
public class AuthenticationHandler extends Handler.Abstract {
202
@Override
203
public boolean handle(Request request, Response response, Callback callback)
204
throws Exception {
205
206
String authHeader = request.getHeaders().get("Authorization");
207
if (authHeader == null || !isValidAuth(authHeader)) {
208
response.setStatus(401);
209
response.getHeaders().put("Content-Type", "text/plain");
210
response.write(true, ByteBuffer.wrap("Unauthorized".getBytes()), callback);
211
return true; // Request handled (rejected)
212
}
213
214
return false; // Continue to next handler
215
}
216
217
private boolean isValidAuth(String authHeader) {
218
// Validate authentication token
219
return authHeader.startsWith("Bearer ") && authHeader.length() > 20;
220
}
221
}
222
```
223
224
## Advanced Handler Patterns
225
226
### Conditional Handler Processing
227
228
```java
229
public abstract class ConditionalHandler extends Handler.Wrapper {
230
231
@Override
232
public boolean handle(Request request, Response response, Callback callback)
233
throws Exception {
234
235
if (shouldHandle(request)) {
236
return handleConditionally(request, response, callback);
237
} else {
238
return super.handle(request, response, callback);
239
}
240
}
241
242
protected abstract boolean shouldHandle(Request request);
243
244
protected boolean handleConditionally(Request request, Response response, Callback callback)
245
throws Exception {
246
// Default: delegate to child
247
return super.handle(request, response, callback);
248
}
249
}
250
251
// IP-based access control
252
public class IPRestrictedHandler extends ConditionalHandler {
253
private final Set<String> allowedIPs;
254
255
public IPRestrictedHandler(Set<String> allowedIPs) {
256
this.allowedIPs = allowedIPs;
257
}
258
259
@Override
260
protected boolean shouldHandle(Request request) {
261
String clientIP = request.getConnectionMetaData()
262
.getRemoteSocketAddress().toString();
263
return !allowedIPs.contains(clientIP);
264
}
265
266
@Override
267
protected boolean handleConditionally(Request request, Response response, Callback callback)
268
throws Exception {
269
// Reject forbidden IPs
270
response.setStatus(403);
271
response.getHeaders().put("Content-Type", "text/plain");
272
response.write(true, ByteBuffer.wrap("Access Denied".getBytes()), callback);
273
return true;
274
}
275
}
276
```
277
278
### Asynchronous Handler Processing
279
280
```java
281
public class AsyncProcessingHandler extends Handler.Abstract {
282
private final ExecutorService executor = Executors.newCachedThreadPool();
283
284
@Override
285
public boolean handle(Request request, Response response, Callback callback)
286
throws Exception {
287
288
// Process request asynchronously
289
CompletableFuture.supplyAsync(() -> {
290
try {
291
// Simulate async processing
292
Thread.sleep(1000);
293
return processRequest(request);
294
} catch (Exception e) {
295
throw new RuntimeException(e);
296
}
297
}, executor).thenAccept(result -> {
298
// Generate response
299
response.setStatus(200);
300
response.getHeaders().put("Content-Type", "application/json");
301
302
String json = "{\"result\": \"" + result + "\", \"async\": true}";
303
response.write(true, ByteBuffer.wrap(json.getBytes()), callback);
304
305
}).exceptionally(throwable -> {
306
// Handle error
307
response.setStatus(500);
308
response.getHeaders().put("Content-Type", "text/plain");
309
response.write(true, ByteBuffer.wrap("Processing failed".getBytes()), callback);
310
return null;
311
});
312
313
return true; // Request handling started
314
}
315
316
private String processRequest(Request request) {
317
// Simulate complex processing
318
return "Processed: " + request.getHttpURI().getPath();
319
}
320
321
@Override
322
protected void doStop() throws Exception {
323
executor.shutdown();
324
super.doStop();
325
}
326
}
327
```
328
329
## Handler Collections and Containers
330
331
### Handler.Collection Interface
332
333
```java { .api }
334
public interface Handler.Collection extends Handler.Container {
335
// Inherited from Container:
336
List<Handler> getHandlers();
337
boolean insertHandler(Handler handler);
338
boolean removeHandler(Handler handler);
339
340
// Collection-specific operations
341
void setHandlers(List<Handler> handlers);
342
void addHandler(Handler handler);
343
}
344
```
345
346
### Handler.Container Interface
347
348
```java { .api }
349
public interface Handler.Container extends Handler {
350
List<Handler> getHandlers();
351
boolean insertHandler(Handler handler);
352
boolean removeHandler(Handler handler);
353
354
// Descendants and lifecycle management
355
Handler getDescendant(Class<? extends Handler> type);
356
<T extends Handler> List<T> getDescendants(Class<T> type);
357
}
358
```
359
360
## Handler Utilities
361
362
### Handler Tree Navigation
363
364
```java
365
public class HandlerTreeExample {
366
public void exploreHandlerTree(Handler root) {
367
if (root instanceof Handler.Container) {
368
Handler.Container container = (Handler.Container) root;
369
370
// Get all child handlers
371
List<Handler> children = container.getHandlers();
372
373
// Find specific handler type
374
Handler errorHandler = container.getDescendant(ErrorHandler.class);
375
376
// Find all handlers of specific type
377
List<StatisticsHandler> statsHandlers =
378
container.getDescendants(StatisticsHandler.class);
379
380
// Process each child
381
for (Handler child : children) {
382
System.out.println("Handler: " + child.getClass().getSimpleName());
383
exploreHandlerTree(child); // Recursive traversal
384
}
385
}
386
}
387
}
388
```
389
390
### Dynamic Handler Management
391
392
```java
393
public class DynamicHandlerManager {
394
private final Handler.Sequence mainHandler;
395
396
public DynamicHandlerManager() {
397
this.mainHandler = new Handler.Sequence();
398
}
399
400
public void addMiddleware(Handler middleware) {
401
// Insert before the last handler (usually the application handler)
402
List<Handler> handlers = new ArrayList<>(mainHandler.getHandlers());
403
if (handlers.size() > 0) {
404
handlers.add(handlers.size() - 1, middleware);
405
} else {
406
handlers.add(middleware);
407
}
408
mainHandler.setHandlers(handlers);
409
}
410
411
public void removeMiddleware(Class<? extends Handler> middlewareType) {
412
List<Handler> handlers = new ArrayList<>(mainHandler.getHandlers());
413
handlers.removeIf(h -> middlewareType.isInstance(h));
414
mainHandler.setHandlers(handlers);
415
}
416
417
public Handler getRootHandler() {
418
return mainHandler;
419
}
420
}
421
422
// Usage
423
DynamicHandlerManager manager = new DynamicHandlerManager();
424
manager.addMiddleware(new LoggingHandler());
425
manager.addMiddleware(new AuthenticationHandler());
426
manager.addMiddleware(new ApplicationHandler());
427
428
server.setHandler(manager.getRootHandler());
429
```
430
431
## Handler Lifecycle
432
433
All handlers participate in the server lifecycle:
434
435
```java
436
public class LifecycleAwareHandler extends Handler.Abstract {
437
438
@Override
439
protected void doStart() throws Exception {
440
super.doStart();
441
System.out.println("Handler starting: " + this.getClass().getSimpleName());
442
443
// Initialize resources
444
initializeDatabase();
445
startBackgroundTasks();
446
}
447
448
@Override
449
protected void doStop() throws Exception {
450
System.out.println("Handler stopping: " + this.getClass().getSimpleName());
451
452
// Cleanup resources
453
stopBackgroundTasks();
454
closeDatabase();
455
456
super.doStop();
457
}
458
459
private void initializeDatabase() {
460
// Setup database connections
461
}
462
463
private void startBackgroundTasks() {
464
// Start scheduled tasks
465
}
466
467
private void stopBackgroundTasks() {
468
// Stop scheduled tasks
469
}
470
471
private void closeDatabase() {
472
// Close database connections
473
}
474
}
475
```