or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

error-handling.mdfilter-handling.mdindex.mdlisteners.mdmonitoring.mdservlet-context.mdservlet-handling.mdtesting.md

listeners.mddocs/

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

```