0
# Listener Management
1
2
Listener management in Eclipse Jetty provides comprehensive event handling capabilities for servlet context, session, and request lifecycle events through the ListenerHolder and DecoratingListener classes, with support for dependency injection and object decoration.
3
4
## ListenerHolder
5
6
The `ListenerHolder` manages event listener instances and their lifecycle within the servlet context.
7
8
```java { .api }
9
public class ListenerHolder extends BaseHolder<EventListener> {
10
// Constructors
11
public ListenerHolder();
12
public ListenerHolder(Source source);
13
public ListenerHolder(Class<? extends EventListener> listener);
14
15
// Listener instance management
16
public void setListener(EventListener listener);
17
public EventListener getListener();
18
19
// Inherited from BaseHolder
20
public Source getSource();
21
public void initialize();
22
public String getClassName();
23
public Class<? extends EventListener> getHeldClass();
24
public ServletHandler getServletHandler();
25
public void setServletHandler(ServletHandler servletHandler);
26
public void setClassName(String className);
27
public void setHeldClass(Class<? extends EventListener> held);
28
public ServletContext getServletContext();
29
public boolean isInstance();
30
}
31
```
32
33
## DecoratingListener
34
35
The `DecoratingListener` provides object decoration capabilities during servlet context initialization and destruction.
36
37
```java { .api }
38
public class DecoratingListener implements ServletContextAttributeListener {
39
// Constructor
40
public DecoratingListener(ServletContextHandler context, String attributeName);
41
42
// ServletContextAttributeListener implementation
43
public void attributeAdded(ServletContextAttributeEvent event);
44
public void attributeRemoved(ServletContextAttributeEvent event);
45
public void attributeReplaced(ServletContextAttributeEvent event);
46
}
47
```
48
49
## Container Initializer Support
50
51
The listener package also provides utilities for manual execution of ServletContainerInitializer.
52
53
```java { .api }
54
public final class ContainerInitializer {
55
// Static utility method
56
public static ServletContainerInitializerServletContextListener asContextListener(
57
ServletContainerInitializer sci);
58
59
// Inner class for SCI integration
60
public static class ServletContainerInitializerServletContextListener
61
implements ServletContextListener {
62
63
public ServletContainerInitializerServletContextListener(ServletContainerInitializer sci);
64
65
// Configuration methods
66
public ServletContainerInitializerServletContextListener addClasses(String... classNames);
67
public ServletContainerInitializerServletContextListener addClasses(Class<?>... classes);
68
public ServletContainerInitializerServletContextListener afterStartup(
69
Consumer<ServletContext> consumer);
70
71
// Access methods
72
public Set<Class<?>> getClasses();
73
74
// ServletContextListener implementation
75
public void contextInitialized(ServletContextEvent sce);
76
public void contextDestroyed(ServletContextEvent sce);
77
}
78
}
79
```
80
81
## Cleanup Listeners
82
83
Eclipse Jetty provides specialized listeners for cleanup operations.
84
85
### ELContextCleaner
86
87
```java { .api }
88
public class ELContextCleaner implements ServletContextListener {
89
public ELContextCleaner();
90
91
public void contextInitialized(ServletContextEvent sce);
92
public void contextDestroyed(ServletContextEvent sce);
93
}
94
```
95
96
### IntrospectorCleaner
97
98
```java { .api }
99
public class IntrospectorCleaner implements ServletContextListener {
100
public IntrospectorCleaner();
101
102
public void contextInitialized(ServletContextEvent sce);
103
public void contextDestroyed(ServletContextEvent sce);
104
}
105
```
106
107
## Usage Examples
108
109
### Basic Listener Registration
110
111
```java
112
import org.eclipse.jetty.servlet.ListenerHolder;
113
import org.eclipse.jetty.servlet.ServletContextHandler;
114
import org.eclipse.jetty.servlet.ServletHandler;
115
import jakarta.servlet.ServletContextEvent;
116
import jakarta.servlet.ServletContextListener;
117
118
// Custom servlet context listener
119
public class ApplicationLifecycleListener implements ServletContextListener {
120
@Override
121
public void contextInitialized(ServletContextEvent sce) {
122
System.out.println("Application context initialized");
123
// Initialize application resources
124
}
125
126
@Override
127
public void contextDestroyed(ServletContextEvent sce) {
128
System.out.println("Application context destroyed");
129
// Cleanup application resources
130
}
131
}
132
133
// Method 1: Add listener via ServletContextHandler
134
ServletContextHandler context = new ServletContextHandler("/myapp");
135
context.addEventListener(new ApplicationLifecycleListener());
136
137
// Method 2: Add listener via ServletHandler using ListenerHolder
138
ServletHandler handler = context.getServletHandler();
139
140
ListenerHolder listenerHolder = new ListenerHolder(ApplicationLifecycleListener.class);
141
handler.addListener(listenerHolder);
142
143
// Method 3: Create listener holder with instance
144
ListenerHolder instanceHolder = new ListenerHolder(new ApplicationLifecycleListener());
145
handler.addListener(instanceHolder);
146
```
147
148
### Multiple Listener Types
149
150
```java
151
import jakarta.servlet.ServletContextListener;
152
import jakarta.servlet.ServletContextAttributeListener;
153
import jakarta.servlet.ServletRequestListener;
154
import jakarta.servlet.ServletRequestAttributeListener;
155
import jakarta.servlet.http.HttpSessionListener;
156
import jakarta.servlet.http.HttpSessionAttributeListener;
157
158
// Comprehensive listener implementation
159
public class ComprehensiveListener implements
160
ServletContextListener,
161
ServletContextAttributeListener,
162
ServletRequestListener,
163
ServletRequestAttributeListener,
164
HttpSessionListener,
165
HttpSessionAttributeListener {
166
167
// ServletContextListener methods
168
@Override
169
public void contextInitialized(ServletContextEvent sce) {
170
System.out.println("Context initialized");
171
}
172
173
@Override
174
public void contextDestroyed(ServletContextEvent sce) {
175
System.out.println("Context destroyed");
176
}
177
178
// ServletContextAttributeListener methods
179
@Override
180
public void attributeAdded(ServletContextAttributeEvent scae) {
181
System.out.println("Context attribute added: " + scae.getName());
182
}
183
184
@Override
185
public void attributeRemoved(ServletContextAttributeEvent scae) {
186
System.out.println("Context attribute removed: " + scae.getName());
187
}
188
189
@Override
190
public void attributeReplaced(ServletContextAttributeEvent scae) {
191
System.out.println("Context attribute replaced: " + scae.getName());
192
}
193
194
// ServletRequestListener methods
195
@Override
196
public void requestInitialized(ServletRequestEvent sre) {
197
System.out.println("Request initialized");
198
}
199
200
@Override
201
public void requestDestroyed(ServletRequestEvent sre) {
202
System.out.println("Request destroyed");
203
}
204
205
// ServletRequestAttributeListener methods
206
@Override
207
public void attributeAdded(ServletRequestAttributeEvent srae) {
208
System.out.println("Request attribute added: " + srae.getName());
209
}
210
211
@Override
212
public void attributeRemoved(ServletRequestAttributeEvent srae) {
213
System.out.println("Request attribute removed: " + srae.getName());
214
}
215
216
@Override
217
public void attributeReplaced(ServletRequestAttributeEvent srae) {
218
System.out.println("Request attribute replaced: " + srae.getName());
219
}
220
221
// HttpSessionListener methods
222
@Override
223
public void sessionCreated(HttpSessionEvent se) {
224
System.out.println("Session created: " + se.getSession().getId());
225
}
226
227
@Override
228
public void sessionDestroyed(HttpSessionEvent se) {
229
System.out.println("Session destroyed: " + se.getSession().getId());
230
}
231
232
// HttpSessionAttributeListener methods
233
@Override
234
public void attributeAdded(HttpSessionBindingEvent se) {
235
System.out.println("Session attribute added: " + se.getName());
236
}
237
238
@Override
239
public void attributeRemoved(HttpSessionBindingEvent se) {
240
System.out.println("Session attribute removed: " + se.getName());
241
}
242
243
@Override
244
public void attributeReplaced(HttpSessionBindingEvent se) {
245
System.out.println("Session attribute replaced: " + se.getName());
246
}
247
}
248
249
// Register comprehensive listener
250
ListenerHolder comprehensiveListener = new ListenerHolder(ComprehensiveListener.class);
251
handler.addListener(comprehensiveListener);
252
```
253
254
### Decorating Listener for Dependency Injection
255
256
```java
257
import org.eclipse.jetty.servlet.DecoratingListener;
258
import org.eclipse.jetty.util.DecoratedObjectFactory;
259
import org.eclipse.jetty.util.Decorator;
260
261
// Custom decorator for dependency injection
262
public class DependencyInjectionDecorator implements Decorator {
263
@Override
264
public <T> T decorate(T o) {
265
if (o instanceof Injectable) {
266
((Injectable) o).inject();
267
}
268
return o;
269
}
270
271
@Override
272
public void destroy(Object o) {
273
if (o instanceof Injectable) {
274
((Injectable) o).cleanup();
275
}
276
}
277
}
278
279
// Interface for injectable objects
280
public interface Injectable {
281
void inject();
282
void cleanup();
283
}
284
285
// Injectable servlet example
286
public class InjectableServlet extends HttpServlet implements Injectable {
287
private DatabaseService dbService;
288
289
@Override
290
public void inject() {
291
this.dbService = ServiceLocator.getInstance().getService(DatabaseService.class);
292
System.out.println("Dependencies injected into servlet");
293
}
294
295
@Override
296
public void cleanup() {
297
if (dbService != null) {
298
dbService.close();
299
System.out.println("Dependencies cleaned up in servlet");
300
}
301
}
302
}
303
304
// Configure decorating listener
305
ServletContextHandler context = new ServletContextHandler("/app");
306
307
// Create decorating listener for a specific context attribute
308
DecoratingListener decorator = new DecoratingListener(context, "dependencyInjector");
309
context.addEventListener(decorator);
310
311
// Add injectable servlet
312
context.addServlet(InjectableServlet.class, "/injectable/*");
313
```
314
315
### ServletContainerInitializer Integration
316
317
```java
318
import org.eclipse.jetty.servlet.listener.ContainerInitializer;
319
import jakarta.servlet.ServletContainerInitializer;
320
import jakarta.servlet.ServletContext;
321
import jakarta.servlet.annotation.HandlesTypes;
322
import java.util.Set;
323
324
// Custom ServletContainerInitializer
325
@HandlesTypes({WebServlet.class, WebFilter.class, WebListener.class})
326
public class AnnotationScanner implements ServletContainerInitializer {
327
@Override
328
public void onStartup(Set<Class<?>> webAppInitializerClasses,
329
ServletContext servletContext) {
330
if (webAppInitializerClasses != null) {
331
for (Class<?> clazz : webAppInitializerClasses) {
332
System.out.println("Found annotated class: " + clazz.getName());
333
334
// Process WebServlet annotations
335
if (clazz.isAnnotationPresent(WebServlet.class)) {
336
// Register servlet dynamically
337
}
338
339
// Process WebFilter annotations
340
if (clazz.isAnnotationPresent(WebFilter.class)) {
341
// Register filter dynamically
342
}
343
344
// Process WebListener annotations
345
if (clazz.isAnnotationPresent(WebListener.class)) {
346
// Register listener dynamically
347
}
348
}
349
}
350
}
351
}
352
353
// Convert SCI to ServletContextListener
354
ContainerInitializer.ServletContainerInitializerServletContextListener sciListener =
355
ContainerInitializer.asContextListener(new AnnotationScanner());
356
357
// Add classes that should be scanned
358
sciListener.addClasses(
359
"com.example.MyServlet",
360
"com.example.MyFilter",
361
"com.example.MyListener"
362
);
363
364
// Add class objects
365
sciListener.addClasses(
366
MyServlet.class,
367
MyFilter.class,
368
MyListener.class
369
);
370
371
// Set post-startup callback
372
sciListener.afterStartup(servletContext -> {
373
System.out.println("ServletContainerInitializer execution completed");
374
// Additional post-startup logic
375
});
376
377
// Add to context
378
context.addEventListener(sciListener);
379
```
380
381
### Cleanup Listeners
382
383
```java
384
import org.eclipse.jetty.servlet.listener.ELContextCleaner;
385
import org.eclipse.jetty.servlet.listener.IntrospectorCleaner;
386
387
// Add cleanup listeners to prevent memory leaks
388
ServletContextHandler context = new ServletContextHandler("/webapp");
389
390
// EL Context cleaner - cleans up Expression Language context
391
context.addEventListener(new ELContextCleaner());
392
393
// Introspector cleaner - cleans up Java Bean introspector caches
394
context.addEventListener(new IntrospectorCleaner());
395
396
// Custom cleanup listener
397
public class ResourceCleanupListener implements ServletContextListener {
398
@Override
399
public void contextInitialized(ServletContextEvent sce) {
400
// No action needed on initialization
401
}
402
403
@Override
404
public void contextDestroyed(ServletContextEvent sce) {
405
// Cleanup application resources
406
System.out.println("Cleaning up application resources...");
407
408
// Stop background threads
409
ThreadPoolManager.shutdown();
410
411
// Close database connections
412
DatabaseConnectionPool.closeAll();
413
414
// Clear caches
415
CacheManager.clearAll();
416
417
// Cleanup temporary files
418
TemporaryFileManager.cleanup();
419
420
System.out.println("Application resources cleaned up");
421
}
422
}
423
424
context.addEventListener(new ResourceCleanupListener());
425
```
426
427
### Listener Configuration and Management
428
429
```java
430
import org.eclipse.jetty.servlet.Source;
431
432
// Create listener holders with different sources
433
ListenerHolder embeddedListener = new ListenerHolder(Source.EMBEDDED);
434
embeddedListener.setHeldClass(EmbeddedListener.class);
435
436
ListenerHolder apiListener = new ListenerHolder(Source.JAVAX_API);
437
apiListener.setClassName("com.example.ApiListener");
438
439
ListenerHolder descriptorListener = new ListenerHolder(Source.DESCRIPTOR);
440
descriptorListener.setListener(new DescriptorListener());
441
442
// Add listeners to handler
443
ServletHandler handler = context.getServletHandler();
444
handler.addListener(embeddedListener);
445
handler.addListener(apiListener);
446
handler.addListener(descriptorListener);
447
448
// Get all listeners
449
ListenerHolder[] listeners = handler.getListeners();
450
for (ListenerHolder listener : listeners) {
451
System.out.println("Listener: " + listener.getClassName() +
452
" (source: " + listener.getSource().getOrigin() + ")");
453
}
454
455
// Initialize specific listener
456
try {
457
embeddedListener.initialize();
458
EventListener listenerInstance = embeddedListener.getListener();
459
System.out.println("Listener initialized: " + listenerInstance.getClass().getName());
460
} catch (Exception e) {
461
System.err.println("Failed to initialize listener: " + e.getMessage());
462
}
463
```
464
465
### Listener Lifecycle Management
466
467
```java
468
public class LifecycleAwareListener implements ServletContextListener {
469
private boolean initialized = false;
470
471
@Override
472
public void contextInitialized(ServletContextEvent sce) {
473
try {
474
// Initialize resources
475
initializeResources();
476
477
// Mark as initialized
478
initialized = true;
479
480
System.out.println("Listener successfully initialized");
481
} catch (Exception e) {
482
System.err.println("Failed to initialize listener: " + e.getMessage());
483
throw new RuntimeException("Listener initialization failed", e);
484
}
485
}
486
487
@Override
488
public void contextDestroyed(ServletContextEvent sce) {
489
if (initialized) {
490
try {
491
// Cleanup resources
492
cleanupResources();
493
494
System.out.println("Listener successfully cleaned up");
495
} catch (Exception e) {
496
System.err.println("Error during listener cleanup: " + e.getMessage());
497
} finally {
498
initialized = false;
499
}
500
}
501
}
502
503
private void initializeResources() {
504
// Resource initialization logic
505
}
506
507
private void cleanupResources() {
508
// Resource cleanup logic
509
}
510
}
511
512
// Configure with proper error handling
513
ListenerHolder lifecycleListener = new ListenerHolder(LifecycleAwareListener.class);
514
515
try {
516
handler.addListener(lifecycleListener);
517
System.out.println("Lifecycle listener registered successfully");
518
} catch (Exception e) {
519
System.err.println("Failed to register listener: " + e.getMessage());
520
}
521
```