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

filter-handling.mddocs/

0

# Filter Handling

1

2

Filter handling in Eclipse Jetty provides comprehensive request/response filtering capabilities with support for different dispatcher types, URL pattern matching, and lifecycle management through the FilterHolder and FilterMapping classes.

3

4

## FilterHolder

5

6

The `FilterHolder` manages individual filter instances, their configuration, and lifecycle.

7

8

```java { .api }

9

public class FilterHolder extends Holder<Filter> {

10

// Constructors

11

public FilterHolder();

12

public FilterHolder(Source source);

13

public FilterHolder(Class<? extends Filter> filter);

14

public FilterHolder(Filter filter);

15

16

// Filter instance management

17

public void setFilter(Filter filter);

18

public Filter getFilter();

19

20

// Lifecycle management

21

public void doStart();

22

public void initialize();

23

public void doStop();

24

public void destroyInstance(Object instance);

25

26

// Registration access

27

public FilterRegistration.Dynamic getRegistration();

28

29

// String representation

30

public String toString();

31

}

32

```

33

34

## FilterMapping

35

36

The `FilterMapping` class defines how filters are applied to requests based on URL patterns, servlet names, and dispatcher types.

37

38

```java { .api }

39

public class FilterMapping implements Dumpable {

40

// Dispatcher type constants

41

public static final int DEFAULT = 0;

42

public static final int REQUEST = 1;

43

public static final int FORWARD = 2;

44

public static final int INCLUDE = 4;

45

public static final int ERROR = 8;

46

public static final int ASYNC = 16;

47

public static final int ALL = 31;

48

49

// Constructor

50

public FilterMapping();

51

52

// Filter identification

53

public String getFilterName();

54

public void setFilterName(String filterName);

55

56

// URL pattern mapping

57

public String[] getPathSpecs();

58

public void setPathSpecs(String[] pathSpecs);

59

public void setPathSpec(String pathSpec);

60

61

// Servlet name mapping

62

public String[] getServletNames();

63

public void setServletNames(String[] servletNames);

64

public void setServletName(String servletName);

65

66

// Dispatcher type configuration

67

public EnumSet<DispatcherType> getDispatcherTypes();

68

public void setDispatcherTypes(EnumSet<DispatcherType> dispatcherTypes);

69

public void setDispatches(int dispatches);

70

public int getDispatches();

71

72

// Mapping properties

73

public boolean isDefaultMapping();

74

public boolean isMatchAfter();

75

public void setMatchAfter(boolean matchAfter);

76

77

// Utility methods

78

public String toString();

79

public void dump(Appendable out, String indent);

80

}

81

```

82

83

## Usage Examples

84

85

### Basic Filter Registration

86

87

```java

88

import org.eclipse.jetty.servlet.FilterHolder;

89

import org.eclipse.jetty.servlet.FilterMapping;

90

import org.eclipse.jetty.servlet.ServletHandler;

91

import jakarta.servlet.Filter;

92

import jakarta.servlet.DispatcherType;

93

import java.util.EnumSet;

94

95

// Create servlet handler

96

ServletHandler handler = new ServletHandler();

97

98

// Method 1: Add filter with mapping in one call

99

FilterHolder holder1 = handler.addFilterWithMapping(

100

LoggingFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));

101

102

// Method 2: Add filter and mapping separately

103

FilterHolder holder2 = new FilterHolder("authFilter", AuthenticationFilter.class);

104

handler.addFilter(holder2);

105

106

FilterMapping mapping = new FilterMapping();

107

mapping.setFilterName("authFilter");

108

mapping.setPathSpec("/secure/*");

109

mapping.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD));

110

handler.addFilterMapping(mapping);

111

112

// Method 3: Using class name string

113

FilterHolder holder3 = handler.addFilterWithMapping(

114

"com.example.CacheFilter", "/api/*", EnumSet.of(DispatcherType.REQUEST));

115

```

116

117

### Filter Configuration and Initialization

118

119

```java

120

import org.eclipse.jetty.servlet.FilterHolder;

121

import jakarta.servlet.Filter;

122

import jakarta.servlet.FilterConfig;

123

import jakarta.servlet.ServletException;

124

125

// Create and configure filter holder

126

FilterHolder filterHolder = new FilterHolder("compressionFilter", CompressionFilter.class);

127

128

// Set initialization parameters

129

filterHolder.setInitParameter("threshold", "1024");

130

filterHolder.setInitParameter("mimeTypes", "text/html,text/css,application/javascript");

131

filterHolder.setInitParameter("enabled", "true");

132

133

// Set display name for management

134

filterHolder.setDisplayName("Content Compression Filter");

135

136

// Enable async support

137

filterHolder.setAsyncSupported(true);

138

139

// Add to handler with specific mapping

140

handler.addFilter(filterHolder);

141

142

// Create detailed mapping

143

FilterMapping mapping = new FilterMapping();

144

mapping.setFilterName("compressionFilter");

145

mapping.setPathSpecs(new String[]{"*.html", "*.css", "*.js", "/api/*"});

146

mapping.setDispatcherTypes(EnumSet.of(

147

DispatcherType.REQUEST,

148

DispatcherType.ASYNC

149

));

150

handler.addFilterMapping(mapping);

151

```

152

153

### Dispatcher Type Configuration

154

155

```java

156

import jakarta.servlet.DispatcherType;

157

import java.util.EnumSet;

158

159

// Security filter for all request types

160

FilterHolder securityFilter = new FilterHolder("security", SecurityFilter.class);

161

FilterMapping securityMapping = new FilterMapping();

162

securityMapping.setFilterName("security");

163

securityMapping.setPathSpec("/secure/*");

164

securityMapping.setDispatcherTypes(EnumSet.of(

165

DispatcherType.REQUEST, // Normal requests

166

DispatcherType.FORWARD, // RequestDispatcher.forward()

167

DispatcherType.INCLUDE, // RequestDispatcher.include()

168

DispatcherType.ERROR, // Error page requests

169

DispatcherType.ASYNC // Async requests

170

));

171

172

// Logging filter for requests only

173

FilterHolder loggingFilter = new FilterHolder("logging", LoggingFilter.class);

174

FilterMapping loggingMapping = new FilterMapping();

175

loggingMapping.setFilterName("logging");

176

loggingMapping.setPathSpec("/*");

177

loggingMapping.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST));

178

179

// Cache filter for requests and forwards

180

FilterHolder cacheFilter = new FilterHolder("cache", CacheFilter.class);

181

FilterMapping cacheMapping = new FilterMapping();

182

cacheMapping.setFilterName("cache");

183

cacheMapping.setPathSpec("/static/*");

184

cacheMapping.setDispatcherTypes(EnumSet.of(

185

DispatcherType.REQUEST,

186

DispatcherType.FORWARD

187

));

188

189

// Add filters to handler

190

handler.addFilter(securityFilter);

191

handler.addFilterMapping(securityMapping);

192

handler.addFilter(loggingFilter);

193

handler.addFilterMapping(loggingMapping);

194

handler.addFilter(cacheFilter);

195

handler.addFilterMapping(cacheMapping);

196

```

197

198

### Multiple Path Patterns

199

200

```java

201

// Filter that handles multiple URL patterns

202

FilterHolder multiPatternFilter = new FilterHolder("multiPattern", MultiPatternFilter.class);

203

204

FilterMapping multiMapping = new FilterMapping();

205

multiMapping.setFilterName("multiPattern");

206

multiMapping.setPathSpecs(new String[]{

207

"/api/v1/*", // API version 1

208

"/api/v2/*", // API version 2

209

"*.json", // All JSON requests

210

"/admin/*", // Admin interface

211

"/reports/*" // Reports section

212

});

213

multiMapping.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST));

214

215

handler.addFilter(multiPatternFilter);

216

handler.addFilterMapping(multiMapping);

217

```

218

219

### Servlet Name Mapping

220

221

```java

222

// Filter that applies to specific servlets by name

223

FilterHolder servletSpecificFilter = new FilterHolder("servletFilter", ServletSpecificFilter.class);

224

225

FilterMapping servletMapping = new FilterMapping();

226

servletMapping.setFilterName("servletFilter");

227

servletMapping.setServletNames(new String[]{

228

"dataServlet", // Apply to data servlet

229

"reportServlet", // Apply to report servlet

230

"adminServlet" // Apply to admin servlet

231

});

232

servletMapping.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST));

233

234

handler.addFilter(servletSpecificFilter);

235

handler.addFilterMapping(servletMapping);

236

237

// Can also set single servlet name

238

FilterMapping singleServletMapping = new FilterMapping();

239

singleServletMapping.setFilterName("servletFilter");

240

singleServletMapping.setServletName("criticalServlet");

241

```

242

243

### Filter Ordering and Chain Management

244

245

```java

246

import org.eclipse.jetty.servlet.ServletHandler;

247

248

// Create handler with filter chain configuration

249

ServletHandler handler = new ServletHandler();

250

251

// Enable filter chain caching for performance

252

handler.setFilterChainsCached(true);

253

handler.setMaxFilterChainsCacheSize(1000);

254

255

// Security filter - should run first

256

FilterHolder securityFilter = new FilterHolder("security", SecurityFilter.class);

257

FilterMapping securityMapping = new FilterMapping();

258

securityMapping.setFilterName("security");

259

securityMapping.setPathSpec("/*");

260

securityMapping.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST));

261

262

// Logging filter - should run after security

263

FilterHolder loggingFilter = new FilterHolder("logging", LoggingFilter.class);

264

FilterMapping loggingMapping = new FilterMapping();

265

loggingMapping.setFilterName("logging");

266

loggingMapping.setPathSpec("/*");

267

loggingMapping.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST));

268

269

// Compression filter - should run last

270

FilterHolder compressionFilter = new FilterHolder("compression", CompressionFilter.class);

271

FilterMapping compressionMapping = new FilterMapping();

272

compressionMapping.setFilterName("compression");

273

compressionMapping.setPathSpec("/*");

274

compressionMapping.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST));

275

276

// Add filters in order (security -> logging -> compression)

277

handler.addFilter(securityFilter);

278

handler.addFilterMapping(securityMapping);

279

280

handler.addFilter(loggingFilter);

281

handler.addFilterMapping(loggingMapping);

282

283

handler.addFilter(compressionFilter);

284

handler.addFilterMapping(compressionMapping);

285

286

// Alternative: Use prepend to insert at beginning of chain

287

FilterMapping emergencyMapping = new FilterMapping();

288

emergencyMapping.setFilterName("emergency");

289

emergencyMapping.setPathSpec("/emergency/*");

290

handler.prependFilterMapping(emergencyMapping);

291

```

292

293

### Advanced Filter Mapping

294

295

```java

296

// Create complex filter with conditional matching

297

FilterHolder conditionalFilter = new FilterHolder("conditional", ConditionalFilter.class);

298

conditionalFilter.setInitParameter("enabledHours", "09:00-17:00");

299

conditionalFilter.setInitParameter("enabledDays", "MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY");

300

301

FilterMapping conditionalMapping = new FilterMapping();

302

conditionalMapping.setFilterName("conditional");

303

conditionalMapping.setPathSpec("/business/*");

304

conditionalMapping.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));

305

306

// Set to match after servlet matching (rare use case)

307

conditionalMapping.setMatchAfter(true);

308

309

handler.addFilter(conditionalFilter);

310

handler.addFilterMapping(conditionalMapping);

311

312

// Check if mapping is default mapping

313

if (conditionalMapping.isDefaultMapping()) {

314

System.out.println("This is a default mapping");

315

}

316

317

// Check match after setting

318

if (conditionalMapping.isMatchAfter()) {

319

System.out.println("Filter matches after servlet matching");

320

}

321

```

322

323

### Filter Lifecycle Management

324

325

```java

326

public class LifecycleAwareFilter implements Filter {

327

private FilterConfig config;

328

329

@Override

330

public void init(FilterConfig filterConfig) throws ServletException {

331

this.config = filterConfig;

332

System.out.println("Filter initialized: " + filterConfig.getFilterName());

333

334

// Access initialization parameters

335

Enumeration<String> paramNames = filterConfig.getInitParameterNames();

336

while (paramNames.hasMoreElements()) {

337

String name = paramNames.nextElement();

338

String value = filterConfig.getInitParameter(name);

339

System.out.println(" " + name + " = " + value);

340

}

341

}

342

343

@Override

344

public void doFilter(ServletRequest request, ServletResponse response,

345

FilterChain chain) throws IOException, ServletException {

346

// Pre-processing

347

long startTime = System.currentTimeMillis();

348

349

try {

350

// Continue filter chain

351

chain.doFilter(request, response);

352

} finally {

353

// Post-processing

354

long duration = System.currentTimeMillis() - startTime;

355

System.out.println("Request processed in " + duration + "ms");

356

}

357

}

358

359

@Override

360

public void destroy() {

361

System.out.println("Filter destroyed: " + config.getFilterName());

362

config = null;

363

}

364

}

365

366

// Configure lifecycle-aware filter

367

FilterHolder lifecycleFilter = new FilterHolder("lifecycle", LifecycleAwareFilter.class);

368

lifecycleFilter.setInitParameter("debug", "true");

369

370

// Start filter (calls init())

371

try {

372

lifecycleFilter.start();

373

} catch (Exception e) {

374

System.err.println("Failed to start filter: " + e.getMessage());

375

}

376

377

// Stop filter (calls destroy())

378

try {

379

lifecycleFilter.stop();

380

} catch (Exception e) {

381

System.err.println("Failed to stop filter: " + e.getMessage());

382

}

383

```

384

385

### Filter Registration and Dynamic Management

386

387

```java

388

import jakarta.servlet.FilterRegistration;

389

390

// Create filter holder and get dynamic registration

391

FilterHolder dynamicFilter = new FilterHolder("dynamic", DynamicFilter.class);

392

handler.addFilter(dynamicFilter);

393

394

// Access filter registration for dynamic configuration

395

FilterRegistration.Dynamic registration = dynamicFilter.getRegistration();

396

397

if (registration != null) {

398

// Set initialization parameters dynamically

399

registration.setInitParameter("runtime.config", "dynamic-value");

400

401

// Set async support

402

registration.setAsyncSupported(true);

403

404

// Add URL patterns dynamically

405

registration.addMappingForUrlPatterns(

406

EnumSet.of(DispatcherType.REQUEST),

407

true, // isMatchAfter

408

"/dynamic/*", "*.dyn"

409

);

410

411

// Add servlet name mappings

412

registration.addMappingForServletNames(

413

EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD),

414

true, // isMatchAfter

415

"dynamicServlet", "testServlet"

416

);

417

}

418

```

419

420

### Error Handling in Filters

421

422

```java

423

public class ErrorHandlingFilter implements Filter {

424

@Override

425

public void doFilter(ServletRequest request, ServletResponse response,

426

FilterChain chain) throws IOException, ServletException {

427

try {

428

chain.doFilter(request, response);

429

} catch (ServletException | IOException e) {

430

// Log error

431

System.err.println("Error in filter chain: " + e.getMessage());

432

433

// Set error attributes for error page

434

request.setAttribute("jakarta.servlet.error.exception", e);

435

request.setAttribute("jakarta.servlet.error.exception_type", e.getClass());

436

request.setAttribute("jakarta.servlet.error.message", e.getMessage());

437

438

// Forward to error page or re-throw

439

if (response instanceof HttpServletResponse) {

440

((HttpServletResponse) response).sendError(500, "Internal Server Error");

441

} else {

442

throw e;

443

}

444

}

445

}

446

}

447

448

// Configure error handling filter to run on ERROR dispatch type

449

FilterHolder errorFilter = new FilterHolder("errorHandler", ErrorHandlingFilter.class);

450

FilterMapping errorMapping = new FilterMapping();

451

errorMapping.setFilterName("errorHandler");

452

errorMapping.setPathSpec("/*");

453

errorMapping.setDispatcherTypes(EnumSet.of(

454

DispatcherType.REQUEST,

455

DispatcherType.ERROR

456

));

457

458

handler.addFilter(errorFilter);

459

handler.addFilterMapping(errorMapping);

460

```