CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-eclipse-jetty-ee10--jetty-ee10-webapp

Jetty web application support for Jakarta EE 10 with full servlet specification compliance

Pending
Overview
Eval results
Files

metadata.mddocs/

Metadata Processing

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.

MetaData Container

The central container for all web application metadata.

public class MetaData {
    
    // Metadata management
    public void clear();
    
    // Descriptor management
    public void setDefaultsDescriptor(DefaultsDescriptor descriptor) 
        throws Exception;
    public void setWebDescriptor(WebDescriptor descriptor) throws Exception;
    public void addOverrideDescriptor(OverrideDescriptor descriptor) 
        throws Exception;
    public void addFragmentDescriptor(Resource jarResource, 
        FragmentDescriptor descriptor) throws Exception;
    
    // Annotation management
    public void addDiscoveredAnnotations(List<DiscoveredAnnotation> annotations);
    public void addDiscoveredAnnotation(DiscoveredAnnotation annotation);
    
    // Processor management
    public void addDescriptorProcessor(DescriptorProcessor p);
    public void removeDescriptorProcessor(DescriptorProcessor p);
    
    // Resolution and validation
    public void resolve(WebAppContext context) throws Exception;
    public boolean isMetaDataComplete();
    public boolean isDistributable();
    
    // Descriptor access
    public WebDescriptor getWebDescriptor();
    public List<WebDescriptor> getOverrideDescriptors();
    public WebDescriptor getDefaultsDescriptor();
    
    // Fragment management
    public boolean isOrdered();
    public Ordering getOrdering();
    public void setOrdering(Ordering o);
    public FragmentDescriptor getFragmentDescriptor(String name);
    public Resource getJarForFragmentName(String name);
    public Map<String, FragmentDescriptor> getNamedFragmentDescriptors();
    
    // Origin tracking
    public Origin getOrigin(String name);
    public OriginInfo getOriginInfo(String name);
    public void setOrigin(String name, Descriptor d);
    public void setOrigin(String name, Annotation annotation, Class<?> annotated);
    public void setOriginAPI(String name);
    
    // Resource management
    public List<Resource> getWebInfResources(boolean withOrdering);
    public List<Resource> getContainerResources();
    
    // Configuration properties
    public boolean isAllowDuplicateFragmentNames();
    public void setAllowDuplicateFragmentNames(boolean allowDuplicateFragmentNames);
    public boolean isValidateXml();
    public void setValidateXml(boolean validateXml);
}

Descriptor Base Classes

Descriptor

Base class for all XML descriptor parsing.

public abstract class Descriptor {
    
    // Constructor
    public Descriptor(Resource resource);
    
    // Parsing
    public void parse(XmlParser parser) throws Exception;
    
    // Access methods
    public String getURI();
    public Resource getResource();
    public XmlParser.Node getRoot();
}

WebDescriptor

Handles web.xml, web-defaults.xml, and web-overrides.xml parsing.

public class WebDescriptor extends Descriptor {
    
    // Static utility methods
    public static boolean isMetaDataComplete(WebDescriptor d);
    public static XmlParser getParser(boolean validating);
    public static XmlParser newParser(boolean validating);
    
    // Metadata properties
    public MetaData.Complete getMetaDataComplete();
    public int getMajorVersion();
    public int getMinorVersion();
    
    // Class name management
    public void addClassName(String className);
    public ArrayList<String> getClassNames();
    
    // Deployment properties
    public boolean isDistributable();
    
    // Ordering information
    public boolean isOrdered();
    public List<String> getOrdering();
}

Specialized Descriptors

public class DefaultsDescriptor extends WebDescriptor {
    // Handles web-defaults.xml parsing
}

public class OverrideDescriptor extends WebDescriptor {
    // Handles web-overrides.xml parsing
}

public class FragmentDescriptor extends WebDescriptor {
    // Handles web-fragment.xml parsing from JAR files
}

Descriptor Processing

DescriptorProcessor Interface

public interface DescriptorProcessor {
    void process(WebAppContext context, Descriptor descriptor) throws Exception;
}

StandardDescriptorProcessor

Processes standard servlet specification descriptors.

public class StandardDescriptorProcessor extends IterativeDescriptorProcessor {
    // Processes web.xml, web-defaults.xml, web-overrides.xml, 
    // and web-fragment.xml descriptors
}

IterativeDescriptorProcessor

Base class for iterative descriptor processing.

public abstract class IterativeDescriptorProcessor 
    implements DescriptorProcessor {
    // Base functionality for iterating through descriptor elements
}

Annotation Discovery

DiscoveredAnnotation

Represents annotations discovered during classpath scanning.

public abstract class DiscoveredAnnotation {
    
    // Constructors
    public DiscoveredAnnotation(WebAppContext context, String className);
    public DiscoveredAnnotation(WebAppContext context, String className, 
        Resource resource);
    
    // Core method - must be implemented by subclasses
    public abstract void apply();
    
    // Access methods
    public String getClassName();
    public Resource getResource();
    public Class<?> getTargetClass();
}

Ordering System

Ordering Interface

public interface Ordering {
    List<Resource> order(List<Resource> fragments);
}

Ordering Implementations

public class AbsoluteOrdering implements Ordering {
    // Implements absolute ordering for fragments
    public List<Resource> order(List<Resource> fragments);
}

public class RelativeOrdering implements Ordering {
    // Implements relative ordering for fragments
    public List<Resource> order(List<Resource> fragments);
}

Origin Tracking

Origin Enum

public enum Origin {
    NotSet, WebXml, WebDefaults, WebOverride, 
    WebFragment, Annotation, API;
    
    public static Origin of(Object o);
}

OriginInfo

public static class MetaData.OriginInfo {
    // Contains detailed information about where metadata originated
}

MetaData Constants

public static final String VALIDATE_XML = 
    "org.eclipse.jetty.ee10.webapp.validateXml";
public static final String ORDERED_LIBS = 
    "org.eclipse.jetty.ee10.webapp.orderedLibs";

MetaData Completion States

public enum MetaData.Complete {
    NotSet, True, False
}

Usage Examples

Basic MetaData Setup

import org.eclipse.jetty.ee10.webapp.*;

WebAppContext context = new WebAppContext();
MetaData metaData = new MetaData();

// Set defaults descriptor
DefaultsDescriptor defaults = new DefaultsDescriptor(
    ResourceFactory.of(context).newResource("webdefault.xml"));
defaults.parse(XmlParser.getParser(true));
metaData.setDefaultsDescriptor(defaults);

// Set main web descriptor
WebDescriptor webXml = new WebDescriptor(
    context.getWebInf().resolve("web.xml"));
webXml.parse(XmlParser.getParser(true));
metaData.setWebDescriptor(webXml);

context.setMetaData(metaData);

Fragment Processing

import org.eclipse.jetty.ee10.webapp.*;

MetaData metaData = context.getMetaData();

// Add fragments from JAR files
Resource jarResource = ResourceFactory.of(context).newResource("lib/fragment.jar");
FragmentDescriptor fragment = new FragmentDescriptor(
    jarResource.resolve("META-INF/web-fragment.xml"));
fragment.parse(XmlParser.getParser(true));

metaData.addFragmentDescriptor(jarResource, fragment);

// Set ordering if specified
if (metaData.isOrdered()) {
    AbsoluteOrdering ordering = new AbsoluteOrdering();
    metaData.setOrdering(ordering);
}

Annotation Discovery and Processing

import org.eclipse.jetty.ee10.webapp.*;

// Custom annotation implementation
public class WebServletAnnotation extends DiscoveredAnnotation {
    
    private WebServlet annotation;
    
    public WebServletAnnotation(WebAppContext context, String className, 
                              Resource resource) {
        super(context, className, resource);
        // Extract annotation details
    }
    
    @Override
    public void apply() {
        // Apply the @WebServlet annotation to context
        ServletHolder holder = new ServletHolder();
        holder.setName(annotation.name());
        holder.setClassName(getClassName());
        
        // Add servlet mapping
        for (String pattern : annotation.urlPatterns()) {
            context.getServletHandler().addServletWithMapping(holder, pattern);
        }
    }
}

// Add discovered annotations
MetaData metaData = context.getMetaData();
List<DiscoveredAnnotation> annotations = new ArrayList<>();
annotations.add(new WebServletAnnotation(context, "com.example.MyServlet", 
    ResourceFactory.of(context).newResource("classes/com/example/MyServlet.class")));

metaData.addDiscoveredAnnotations(annotations);

Custom Descriptor Processing

import org.eclipse.jetty.ee10.webapp.*;

public class CustomDescriptorProcessor implements DescriptorProcessor {
    
    @Override
    public void process(WebAppContext context, Descriptor descriptor) 
            throws Exception {
        
        if (descriptor instanceof WebDescriptor) {
            WebDescriptor webDesc = (WebDescriptor) descriptor;
            XmlParser.Node root = webDesc.getRoot();
            
            // Process custom elements
            XmlParser.Node[] customNodes = root.getNodes("custom-config");
            for (XmlParser.Node node : customNodes) {
                String value = node.toString();
                context.setAttribute("custom.config", value);
            }
        }
    }
}

// Add custom processor
MetaData metaData = context.getMetaData();
metaData.addDescriptorProcessor(new CustomDescriptorProcessor());

Origin Tracking

import org.eclipse.jetty.ee10.webapp.*;

MetaData metaData = context.getMetaData();

// Track origin of configuration elements
metaData.setOrigin("javax.servlet.Servlet", webXmlDescriptor);
metaData.setOrigin("com.example.MyServlet", annotation, MyServlet.class);
metaData.setOriginAPI("ServletContext.addServlet");

// Query origins
Origin servletOrigin = metaData.getOrigin("javax.servlet.Servlet");
OriginInfo info = metaData.getOriginInfo("com.example.MyServlet");

System.out.println("Servlet configuration came from: " + servletOrigin);

MetaData Resolution and Validation

import org.eclipse.jetty.ee10.webapp.*;

WebAppContext context = new WebAppContext();
MetaData metaData = context.getMetaData();

// Enable XML validation
metaData.setValidateXml(true);

// Allow duplicate fragment names if needed
metaData.setAllowDuplicateFragmentNames(false);

try {
    // Resolve all metadata
    metaData.resolve(context);
    
    // Check completion status
    if (metaData.isMetaDataComplete()) {
        System.out.println("Metadata is complete - no annotation scanning needed");
    } else {
        System.out.println("Metadata incomplete - annotation scanning required");
    }
    
    // Check distributability
    if (metaData.isDistributable()) {
        System.out.println("Web application is distributable");
    }
    
} catch (Exception e) {
    System.err.println("Metadata resolution failed: " + e.getMessage());
}

Resource and Fragment Management

import org.eclipse.jetty.ee10.webapp.*;

MetaData metaData = context.getMetaData();

// Get WEB-INF resources with ordering
List<Resource> orderedResources = metaData.getWebInfResources(true);
List<Resource> containerResources = metaData.getContainerResources();

// Access fragment information
Map<String, FragmentDescriptor> fragments = 
    metaData.getNamedFragmentDescriptors();

for (Map.Entry<String, FragmentDescriptor> entry : fragments.entrySet()) {
    String name = entry.getKey();
    FragmentDescriptor fragment = entry.getValue();
    Resource jar = metaData.getJarForFragmentName(name);
    
    System.out.println("Fragment " + name + " from " + jar.getURI());
}

Custom Ordering Implementation

import org.eclipse.jetty.ee10.webapp.*;

public class CustomOrdering implements Ordering {
    
    private List<String> beforeOthers;
    private List<String> afterOthers;
    
    @Override
    public List<Resource> order(List<Resource> fragments) {
        // Custom ordering logic
        List<Resource> ordered = new ArrayList<>(fragments);
        
        // Sort based on custom criteria
        ordered.sort((r1, r2) -> {
            // Compare fragment names, priorities, etc.
            return getFragmentName(r1).compareTo(getFragmentName(r2));
        });
        
        return ordered;
    }
    
    private String getFragmentName(Resource resource) {
        // Extract fragment name from resource
        return resource.getFileName();
    }
}

// Use custom ordering
MetaData metaData = context.getMetaData();
metaData.setOrdering(new CustomOrdering());

Error Handling

Metadata processing can encounter various exceptions:

  • Exception - General parsing or processing errors
  • IOException - I/O errors when reading descriptor files
  • SAXException - XML parsing errors in descriptors
  • ClassNotFoundException - Missing classes referenced in annotations
  • IllegalStateException - Invalid metadata state during resolution

Common error scenarios:

  • Malformed XML in web.xml or fragment files
  • Circular dependencies between fragments
  • Missing or inaccessible descriptor files
  • Invalid metadata-complete settings
  • Conflicting fragment ordering specifications
  • Annotation processing errors for missing classes

Performance Considerations

Metadata Caching

// Enable container metadata caching for better performance
System.setProperty(MetaInfConfiguration.USE_CONTAINER_METAINF_CACHE, "true");

XML Validation Control

// Disable XML validation for faster parsing (development only)
MetaData metaData = context.getMetaData();
metaData.setValidateXml(false);

Fragment Processing Optimization

// Allow duplicate fragment names to reduce validation overhead
MetaData metaData = context.getMetaData();
metaData.setAllowDuplicateFragmentNames(true);

Install with Tessl CLI

npx tessl i tessl/maven-org-eclipse-jetty-ee10--jetty-ee10-webapp

docs

classloader.md

configuration.md

index.md

metadata.md

webapp-context.md

tile.json