0
# Metadata Processing
1
2
The Jetty EE10 WebApp metadata processing system handles comprehensive analysis and resolution of web application descriptors, annotations, and fragment information. It provides a unified view of all configuration sources including web.xml, web-fragment.xml files, and discovered annotations.
3
4
## MetaData Container
5
6
The central container for all web application metadata.
7
8
```java { .api }
9
public class MetaData {
10
11
// Metadata management
12
public void clear();
13
14
// Descriptor management
15
public void setDefaultsDescriptor(DefaultsDescriptor descriptor)
16
throws Exception;
17
public void setWebDescriptor(WebDescriptor descriptor) throws Exception;
18
public void addOverrideDescriptor(OverrideDescriptor descriptor)
19
throws Exception;
20
public void addFragmentDescriptor(Resource jarResource,
21
FragmentDescriptor descriptor) throws Exception;
22
23
// Annotation management
24
public void addDiscoveredAnnotations(List<DiscoveredAnnotation> annotations);
25
public void addDiscoveredAnnotation(DiscoveredAnnotation annotation);
26
27
// Processor management
28
public void addDescriptorProcessor(DescriptorProcessor p);
29
public void removeDescriptorProcessor(DescriptorProcessor p);
30
31
// Resolution and validation
32
public void resolve(WebAppContext context) throws Exception;
33
public boolean isMetaDataComplete();
34
public boolean isDistributable();
35
36
// Descriptor access
37
public WebDescriptor getWebDescriptor();
38
public List<WebDescriptor> getOverrideDescriptors();
39
public WebDescriptor getDefaultsDescriptor();
40
41
// Fragment management
42
public boolean isOrdered();
43
public Ordering getOrdering();
44
public void setOrdering(Ordering o);
45
public FragmentDescriptor getFragmentDescriptor(String name);
46
public Resource getJarForFragmentName(String name);
47
public Map<String, FragmentDescriptor> getNamedFragmentDescriptors();
48
49
// Origin tracking
50
public Origin getOrigin(String name);
51
public OriginInfo getOriginInfo(String name);
52
public void setOrigin(String name, Descriptor d);
53
public void setOrigin(String name, Annotation annotation, Class<?> annotated);
54
public void setOriginAPI(String name);
55
56
// Resource management
57
public List<Resource> getWebInfResources(boolean withOrdering);
58
public List<Resource> getContainerResources();
59
60
// Configuration properties
61
public boolean isAllowDuplicateFragmentNames();
62
public void setAllowDuplicateFragmentNames(boolean allowDuplicateFragmentNames);
63
public boolean isValidateXml();
64
public void setValidateXml(boolean validateXml);
65
}
66
```
67
68
## Descriptor Base Classes
69
70
### Descriptor
71
72
Base class for all XML descriptor parsing.
73
74
```java { .api }
75
public abstract class Descriptor {
76
77
// Constructor
78
public Descriptor(Resource resource);
79
80
// Parsing
81
public void parse(XmlParser parser) throws Exception;
82
83
// Access methods
84
public String getURI();
85
public Resource getResource();
86
public XmlParser.Node getRoot();
87
}
88
```
89
90
### WebDescriptor
91
92
Handles web.xml, web-defaults.xml, and web-overrides.xml parsing.
93
94
```java { .api }
95
public class WebDescriptor extends Descriptor {
96
97
// Static utility methods
98
public static boolean isMetaDataComplete(WebDescriptor d);
99
public static XmlParser getParser(boolean validating);
100
public static XmlParser newParser(boolean validating);
101
102
// Metadata properties
103
public MetaData.Complete getMetaDataComplete();
104
public int getMajorVersion();
105
public int getMinorVersion();
106
107
// Class name management
108
public void addClassName(String className);
109
public ArrayList<String> getClassNames();
110
111
// Deployment properties
112
public boolean isDistributable();
113
114
// Ordering information
115
public boolean isOrdered();
116
public List<String> getOrdering();
117
}
118
```
119
120
### Specialized Descriptors
121
122
```java { .api }
123
public class DefaultsDescriptor extends WebDescriptor {
124
// Handles web-defaults.xml parsing
125
}
126
127
public class OverrideDescriptor extends WebDescriptor {
128
// Handles web-overrides.xml parsing
129
}
130
131
public class FragmentDescriptor extends WebDescriptor {
132
// Handles web-fragment.xml parsing from JAR files
133
}
134
```
135
136
## Descriptor Processing
137
138
### DescriptorProcessor Interface
139
140
```java { .api }
141
public interface DescriptorProcessor {
142
void process(WebAppContext context, Descriptor descriptor) throws Exception;
143
}
144
```
145
146
### StandardDescriptorProcessor
147
148
Processes standard servlet specification descriptors.
149
150
```java { .api }
151
public class StandardDescriptorProcessor extends IterativeDescriptorProcessor {
152
// Processes web.xml, web-defaults.xml, web-overrides.xml,
153
// and web-fragment.xml descriptors
154
}
155
```
156
157
### IterativeDescriptorProcessor
158
159
Base class for iterative descriptor processing.
160
161
```java { .api }
162
public abstract class IterativeDescriptorProcessor
163
implements DescriptorProcessor {
164
// Base functionality for iterating through descriptor elements
165
}
166
```
167
168
## Annotation Discovery
169
170
### DiscoveredAnnotation
171
172
Represents annotations discovered during classpath scanning.
173
174
```java { .api }
175
public abstract class DiscoveredAnnotation {
176
177
// Constructors
178
public DiscoveredAnnotation(WebAppContext context, String className);
179
public DiscoveredAnnotation(WebAppContext context, String className,
180
Resource resource);
181
182
// Core method - must be implemented by subclasses
183
public abstract void apply();
184
185
// Access methods
186
public String getClassName();
187
public Resource getResource();
188
public Class<?> getTargetClass();
189
}
190
```
191
192
## Ordering System
193
194
### Ordering Interface
195
196
```java { .api }
197
public interface Ordering {
198
List<Resource> order(List<Resource> fragments);
199
}
200
```
201
202
### Ordering Implementations
203
204
```java { .api }
205
public class AbsoluteOrdering implements Ordering {
206
// Implements absolute ordering for fragments
207
public List<Resource> order(List<Resource> fragments);
208
}
209
210
public class RelativeOrdering implements Ordering {
211
// Implements relative ordering for fragments
212
public List<Resource> order(List<Resource> fragments);
213
}
214
```
215
216
## Origin Tracking
217
218
### Origin Enum
219
220
```java { .api }
221
public enum Origin {
222
NotSet, WebXml, WebDefaults, WebOverride,
223
WebFragment, Annotation, API;
224
225
public static Origin of(Object o);
226
}
227
```
228
229
### OriginInfo
230
231
```java { .api }
232
public static class MetaData.OriginInfo {
233
// Contains detailed information about where metadata originated
234
}
235
```
236
237
## MetaData Constants
238
239
```java { .api }
240
public static final String VALIDATE_XML =
241
"org.eclipse.jetty.ee10.webapp.validateXml";
242
public static final String ORDERED_LIBS =
243
"org.eclipse.jetty.ee10.webapp.orderedLibs";
244
```
245
246
## MetaData Completion States
247
248
```java { .api }
249
public enum MetaData.Complete {
250
NotSet, True, False
251
}
252
```
253
254
## Usage Examples
255
256
### Basic MetaData Setup
257
258
```java
259
import org.eclipse.jetty.ee10.webapp.*;
260
261
WebAppContext context = new WebAppContext();
262
MetaData metaData = new MetaData();
263
264
// Set defaults descriptor
265
DefaultsDescriptor defaults = new DefaultsDescriptor(
266
ResourceFactory.of(context).newResource("webdefault.xml"));
267
defaults.parse(XmlParser.getParser(true));
268
metaData.setDefaultsDescriptor(defaults);
269
270
// Set main web descriptor
271
WebDescriptor webXml = new WebDescriptor(
272
context.getWebInf().resolve("web.xml"));
273
webXml.parse(XmlParser.getParser(true));
274
metaData.setWebDescriptor(webXml);
275
276
context.setMetaData(metaData);
277
```
278
279
### Fragment Processing
280
281
```java
282
import org.eclipse.jetty.ee10.webapp.*;
283
284
MetaData metaData = context.getMetaData();
285
286
// Add fragments from JAR files
287
Resource jarResource = ResourceFactory.of(context).newResource("lib/fragment.jar");
288
FragmentDescriptor fragment = new FragmentDescriptor(
289
jarResource.resolve("META-INF/web-fragment.xml"));
290
fragment.parse(XmlParser.getParser(true));
291
292
metaData.addFragmentDescriptor(jarResource, fragment);
293
294
// Set ordering if specified
295
if (metaData.isOrdered()) {
296
AbsoluteOrdering ordering = new AbsoluteOrdering();
297
metaData.setOrdering(ordering);
298
}
299
```
300
301
### Annotation Discovery and Processing
302
303
```java
304
import org.eclipse.jetty.ee10.webapp.*;
305
306
// Custom annotation implementation
307
public class WebServletAnnotation extends DiscoveredAnnotation {
308
309
private WebServlet annotation;
310
311
public WebServletAnnotation(WebAppContext context, String className,
312
Resource resource) {
313
super(context, className, resource);
314
// Extract annotation details
315
}
316
317
@Override
318
public void apply() {
319
// Apply the @WebServlet annotation to context
320
ServletHolder holder = new ServletHolder();
321
holder.setName(annotation.name());
322
holder.setClassName(getClassName());
323
324
// Add servlet mapping
325
for (String pattern : annotation.urlPatterns()) {
326
context.getServletHandler().addServletWithMapping(holder, pattern);
327
}
328
}
329
}
330
331
// Add discovered annotations
332
MetaData metaData = context.getMetaData();
333
List<DiscoveredAnnotation> annotations = new ArrayList<>();
334
annotations.add(new WebServletAnnotation(context, "com.example.MyServlet",
335
ResourceFactory.of(context).newResource("classes/com/example/MyServlet.class")));
336
337
metaData.addDiscoveredAnnotations(annotations);
338
```
339
340
### Custom Descriptor Processing
341
342
```java
343
import org.eclipse.jetty.ee10.webapp.*;
344
345
public class CustomDescriptorProcessor implements DescriptorProcessor {
346
347
@Override
348
public void process(WebAppContext context, Descriptor descriptor)
349
throws Exception {
350
351
if (descriptor instanceof WebDescriptor) {
352
WebDescriptor webDesc = (WebDescriptor) descriptor;
353
XmlParser.Node root = webDesc.getRoot();
354
355
// Process custom elements
356
XmlParser.Node[] customNodes = root.getNodes("custom-config");
357
for (XmlParser.Node node : customNodes) {
358
String value = node.toString();
359
context.setAttribute("custom.config", value);
360
}
361
}
362
}
363
}
364
365
// Add custom processor
366
MetaData metaData = context.getMetaData();
367
metaData.addDescriptorProcessor(new CustomDescriptorProcessor());
368
```
369
370
### Origin Tracking
371
372
```java
373
import org.eclipse.jetty.ee10.webapp.*;
374
375
MetaData metaData = context.getMetaData();
376
377
// Track origin of configuration elements
378
metaData.setOrigin("javax.servlet.Servlet", webXmlDescriptor);
379
metaData.setOrigin("com.example.MyServlet", annotation, MyServlet.class);
380
metaData.setOriginAPI("ServletContext.addServlet");
381
382
// Query origins
383
Origin servletOrigin = metaData.getOrigin("javax.servlet.Servlet");
384
OriginInfo info = metaData.getOriginInfo("com.example.MyServlet");
385
386
System.out.println("Servlet configuration came from: " + servletOrigin);
387
```
388
389
### MetaData Resolution and Validation
390
391
```java
392
import org.eclipse.jetty.ee10.webapp.*;
393
394
WebAppContext context = new WebAppContext();
395
MetaData metaData = context.getMetaData();
396
397
// Enable XML validation
398
metaData.setValidateXml(true);
399
400
// Allow duplicate fragment names if needed
401
metaData.setAllowDuplicateFragmentNames(false);
402
403
try {
404
// Resolve all metadata
405
metaData.resolve(context);
406
407
// Check completion status
408
if (metaData.isMetaDataComplete()) {
409
System.out.println("Metadata is complete - no annotation scanning needed");
410
} else {
411
System.out.println("Metadata incomplete - annotation scanning required");
412
}
413
414
// Check distributability
415
if (metaData.isDistributable()) {
416
System.out.println("Web application is distributable");
417
}
418
419
} catch (Exception e) {
420
System.err.println("Metadata resolution failed: " + e.getMessage());
421
}
422
```
423
424
### Resource and Fragment Management
425
426
```java
427
import org.eclipse.jetty.ee10.webapp.*;
428
429
MetaData metaData = context.getMetaData();
430
431
// Get WEB-INF resources with ordering
432
List<Resource> orderedResources = metaData.getWebInfResources(true);
433
List<Resource> containerResources = metaData.getContainerResources();
434
435
// Access fragment information
436
Map<String, FragmentDescriptor> fragments =
437
metaData.getNamedFragmentDescriptors();
438
439
for (Map.Entry<String, FragmentDescriptor> entry : fragments.entrySet()) {
440
String name = entry.getKey();
441
FragmentDescriptor fragment = entry.getValue();
442
Resource jar = metaData.getJarForFragmentName(name);
443
444
System.out.println("Fragment " + name + " from " + jar.getURI());
445
}
446
```
447
448
### Custom Ordering Implementation
449
450
```java
451
import org.eclipse.jetty.ee10.webapp.*;
452
453
public class CustomOrdering implements Ordering {
454
455
private List<String> beforeOthers;
456
private List<String> afterOthers;
457
458
@Override
459
public List<Resource> order(List<Resource> fragments) {
460
// Custom ordering logic
461
List<Resource> ordered = new ArrayList<>(fragments);
462
463
// Sort based on custom criteria
464
ordered.sort((r1, r2) -> {
465
// Compare fragment names, priorities, etc.
466
return getFragmentName(r1).compareTo(getFragmentName(r2));
467
});
468
469
return ordered;
470
}
471
472
private String getFragmentName(Resource resource) {
473
// Extract fragment name from resource
474
return resource.getFileName();
475
}
476
}
477
478
// Use custom ordering
479
MetaData metaData = context.getMetaData();
480
metaData.setOrdering(new CustomOrdering());
481
```
482
483
## Error Handling
484
485
Metadata processing can encounter various exceptions:
486
487
- `Exception` - General parsing or processing errors
488
- `IOException` - I/O errors when reading descriptor files
489
- `SAXException` - XML parsing errors in descriptors
490
- `ClassNotFoundException` - Missing classes referenced in annotations
491
- `IllegalStateException` - Invalid metadata state during resolution
492
493
Common error scenarios:
494
- Malformed XML in web.xml or fragment files
495
- Circular dependencies between fragments
496
- Missing or inaccessible descriptor files
497
- Invalid metadata-complete settings
498
- Conflicting fragment ordering specifications
499
- Annotation processing errors for missing classes
500
501
## Performance Considerations
502
503
### Metadata Caching
504
505
```java
506
// Enable container metadata caching for better performance
507
System.setProperty(MetaInfConfiguration.USE_CONTAINER_METAINF_CACHE, "true");
508
```
509
510
### XML Validation Control
511
512
```java
513
// Disable XML validation for faster parsing (development only)
514
MetaData metaData = context.getMetaData();
515
metaData.setValidateXml(false);
516
```
517
518
### Fragment Processing Optimization
519
520
```java
521
// Allow duplicate fragment names to reduce validation overhead
522
MetaData metaData = context.getMetaData();
523
metaData.setAllowDuplicateFragmentNames(true);
524
```