Jetty web application support for Jakarta EE 10 with full servlet specification compliance
—
The Jetty EE10 WebApp configuration system provides a pluggable architecture for handling different aspects of web application setup and servlet specification compliance. Each Configuration implementation handles specific features like web.xml processing, annotation scanning, or security setup.
public interface Configuration {
// Optional configuration properties
default boolean isAvailable();
default Class<? extends Configuration> replaces();
default Collection<String> getDependencies();
default Collection<String> getDependents();
default ClassMatcher getProtectedClasses();
default ClassMatcher getHiddenClasses();
// Required lifecycle methods
void preConfigure(WebAppContext context) throws Exception;
void configure(WebAppContext context) throws Exception;
void postConfigure(WebAppContext context) throws Exception;
void deconfigure(WebAppContext context) throws Exception;
void destroy(WebAppContext context) throws Exception;
// Configuration behavior
boolean isEnabledByDefault();
boolean abort(WebAppContext context);
}Base implementation providing common functionality and builder pattern support.
public abstract class AbstractConfiguration implements Configuration {
// Constructor
protected AbstractConfiguration(Builder builder);
// Dependency management
public Collection<String> getDependents();
public Collection<String> getDependencies();
public ClassMatcher getProtectedClasses();
public ClassMatcher getHiddenClasses();
// Lifecycle implementation
public void preConfigure(WebAppContext context) throws Exception;
public void configure(WebAppContext context) throws Exception;
public void postConfigure(WebAppContext context) throws Exception;
public void deconfigure(WebAppContext context) throws Exception;
public void destroy(WebAppContext context) throws Exception;
// Configuration properties
public boolean isEnabledByDefault();
public boolean abort(WebAppContext context);
}Fluent builder for creating AbstractConfiguration instances.
public static class AbstractConfiguration.Builder {
// Configuration properties
public Builder enabledByDefault(boolean enabledByDefault);
// Dependency management
public Builder addDependencies(String... classes);
public Builder addDependencies(Class<? extends Configuration>... classes);
public Builder addDependents(String... classes);
public Builder addDependents(Class<?>... classes);
// Class visibility controls
public Builder protect(String... classes);
public Builder hide(String... classes);
public Builder expose(String... classes);
public Builder protectAndExpose(String... classes);
}Manages an ordered list of Configuration instances with dependency resolution.
public class Configurations extends AbstractList<Configuration>
implements Dumpable {
// Constructors
public Configurations();
public Configurations(List<Configuration> configurations);
public Configurations(Configuration... configurations);
public Configurations(String... configurationClassNames);
// Static configuration management
public static List<Configuration> getKnown();
public static void setKnown(String... classes);
public static Configurations setServerDefault(Server server);
public static Configurations getServerDefault(Server server);
// Configuration manipulation
public boolean add(Configuration configuration);
public void add(Configuration... configurations);
public void add(String... configClass);
public void clear();
public void set(Configuration... configurations);
public void set(String... configClass);
public void remove(Configuration... configurations);
public void remove(Class<? extends Configuration>... configClass);
public void remove(String... configClass);
// Configuration lookup
public <T> T get(Class<? extends T> configClass);
public <T> List<T> getConfigurations(Class<? extends T> configClass);
// Dependency resolution
public void sort();
public static void sort(List<Configuration> configurations);
// Lifecycle execution
public void preConfigure(WebAppContext webapp) throws Exception;
public boolean configure(WebAppContext webapp) throws Exception;
public void postConfigure(WebAppContext webapp) throws Exception;
}Processes web.xml and web-defaults.xml descriptors.
public class WebXmlConfiguration extends AbstractConfiguration {
// Configures WebApp by parsing default web.xml and web.xml descriptors
}Handles WEB-INF directory processing including extraction and temporary directory setup.
public class WebInfConfiguration extends AbstractConfiguration {
// Temporary directory and extraction
public void resolveTempDirectory(WebAppContext context) throws Exception;
public void unpack(WebAppContext context) throws IOException;
}Scans META-INF of JARs to find TLDs, web-fragment.xml, and resources.
public class MetaInfConfiguration extends AbstractConfiguration {
// JAR scanning methods
public void findAndFilterContainerPaths(WebAppContext context)
throws Exception;
public void findAndFilterWebAppPaths(WebAppContext context)
throws Exception;
public void scanJars(WebAppContext context, Collection<Resource> jars,
boolean useCaches) throws Exception;
public void scanJars(WebAppContext context, Collection<Resource> jars,
boolean useCaches, List<String> scanTypes) throws Exception;
// Specific scanning operations
public void scanForResources(WebAppContext context, Resource dir,
ConcurrentHashMap<Resource, Resource> cache);
public void scanForFragment(WebAppContext context, Resource dir,
ConcurrentHashMap<Resource, Resource> cache);
public void scanForTlds(WebAppContext context, Resource dir,
ConcurrentHashMap<Resource, Collection<URL>> cache) throws Exception;
}Processes jetty-web.xml and jetty-ee10-web.xml configuration files.
public class JettyWebXmlConfiguration extends AbstractConfiguration {
// Processes Jetty-specific configuration files
}Processes web-fragments in JARs.
public class FragmentConfiguration extends AbstractConfiguration {
// Handles web-fragment.xml processing from JAR files
}Configures WebAppContext server/system classes to see default servlets.
public class WebAppConfiguration extends AbstractConfiguration {
// Configures class visibility for default Jetty servlets
}Configures WebAppContext to expose Jetty utility servlets if available.
public class ServletsConfiguration extends AbstractConfiguration {
// Exposes utility servlets like DefaultServlet
}Configures WebAppContext to access JNDI packages.
public class JndiConfiguration extends AbstractConfiguration {
// Enables JNDI support for web applications
}public class JaasConfiguration extends AbstractConfiguration {
// JAAS authentication support
}
public class JaspiConfiguration extends AbstractConfiguration {
// JASPI authentication support
}
public class JmxConfiguration extends AbstractConfiguration {
// JMX monitoring support
}
public class JspConfiguration extends AbstractConfiguration {
// JSP compilation and runtime support
}public static final String USE_CONTAINER_METAINF_CACHE =
"org.eclipse.jetty.metainf.useCache";
public static final String CACHED_CONTAINER_TLDS =
"org.eclipse.jetty.ee10.webapp.containerTlds";
public static final String CACHED_CONTAINER_FRAGMENTS =
"org.eclipse.jetty.ee10.webapp.containerFragments";
public static final String CACHED_CONTAINER_RESOURCES =
"org.eclipse.jetty.ee10.webapp.containerResources";
public static final String METAINF_TLDS =
"org.eclipse.jetty.ee10.webapp.MetaInfTlds";
public static final String METAINF_FRAGMENTS =
"org.eclipse.jetty.ee10.webapp.MetaInfFragments";
public static final String METAINF_RESOURCES =
"org.eclipse.jetty.ee10.webapp.MetaInfResources";
public static final String CONTAINER_JAR_PATTERN =
"org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern";
public static final String WEBINF_JAR_PATTERN =
"org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern";
public static final String RESOURCE_DIRS =
"org.eclipse.jetty.ee10.webapp.resourceDirs";public static final String PROPERTY_WEB_INF_URI =
"org.eclipse.jetty.ee10.webapp.webInfUri";
public static final String PROPERTY_WEB_INF =
"org.eclipse.jetty.ee10.webapp.webInf";
public static final String XML_CONFIGURATION =
"org.eclipse.jetty.ee10.webapp.configuration";
public static final String JETTY_WEB_XML = "jetty-web.xml";
public static final String JETTY_EE10_WEB_XML = "jetty-ee10-web.xml";public static final String FRAGMENT_RESOURCES =
"org.eclipse.jetty.ee10.webapp.fragmentResources";import org.eclipse.jetty.ee10.webapp.*;
WebAppContext webapp = new WebAppContext();
webapp.setWar("/path/to/webapp.war");
webapp.setContextPath("/myapp");
// Use default configurations with automatic discovery
webapp.setConfigurationDiscovered(true);
// Or set specific configurations
Configurations configs = new Configurations();
configs.add(new WebXmlConfiguration());
configs.add(new MetaInfConfiguration());
configs.add(new FragmentConfiguration());
webapp.setConfigurations(configs);import org.eclipse.jetty.ee10.webapp.AbstractConfiguration;
public class CustomConfiguration extends AbstractConfiguration {
public CustomConfiguration() {
super(new Builder()
.enabledByDefault(true)
.addDependencies(WebXmlConfiguration.class)
.protect("com.mycompany.server.")
.hide("com.mycompany.internal.")
);
}
@Override
public void preConfigure(WebAppContext context) throws Exception {
// Pre-configuration logic
System.out.println("Pre-configuring custom features");
}
@Override
public void configure(WebAppContext context) throws Exception {
// Main configuration logic
context.setAttribute("custom.configured", true);
}
@Override
public void postConfigure(WebAppContext context) throws Exception {
// Post-configuration logic
System.out.println("Custom configuration completed");
}
}
// Use custom configuration
WebAppContext webapp = new WebAppContext();
Configurations configs = new Configurations();
configs.add(new WebXmlConfiguration());
configs.add(new CustomConfiguration());
webapp.setConfigurations(configs);import org.eclipse.jetty.ee10.webapp.*;
// Create configurations with explicit dependencies
Configurations configs = new Configurations();
// WebXmlConfiguration has no dependencies
configs.add(new WebXmlConfiguration());
// MetaInfConfiguration depends on WebXmlConfiguration
configs.add(new MetaInfConfiguration());
// FragmentConfiguration depends on both WebXml and MetaInf
configs.add(new FragmentConfiguration());
// JettyWebXmlConfiguration depends on all previous ones
configs.add(new JettyWebXmlConfiguration());
// Sort to resolve dependencies automatically
configs.sort();
WebAppContext webapp = new WebAppContext();
webapp.setConfigurations(configs);import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.ee10.webapp.Configurations;
Server server = new Server();
// Set server-wide default configurations
Configurations.setServerDefault(server);
// Or set custom server defaults
Configurations serverConfigs = new Configurations();
serverConfigs.add(new WebXmlConfiguration());
serverConfigs.add(new MetaInfConfiguration());
// ... add other configurations
Configurations.setServerDefault(server, serverConfigs);
// WebApps will inherit these configurations by default
WebAppContext webapp = new WebAppContext();
// Will use server default configurationsimport org.eclipse.jetty.ee10.webapp.*;
WebAppContext webapp = new WebAppContext();
// Start with all known configurations
Configurations configs = new Configurations(Configurations.getKnown());
// Remove specific configurations
configs.remove(JspConfiguration.class);
configs.remove(JmxConfiguration.class);
// Add custom configuration
configs.add(new CustomConfiguration());
// Get specific configuration type
MetaInfConfiguration metaInfConfig = configs.get(MetaInfConfiguration.class);
if (metaInfConfig != null) {
// Configure MetaInf-specific settings
}
webapp.setConfigurations(configs);import org.eclipse.jetty.ee10.webapp.*;
WebAppContext webapp = new WebAppContext();
webapp.setWar("/path/to/webapp.war");
Configurations configs = new Configurations();
configs.add(new WebXmlConfiguration());
configs.add(new MetaInfConfiguration());
try {
// Execute configuration phases manually
configs.preConfigure(webapp);
boolean success = configs.configure(webapp);
if (success) {
configs.postConfigure(webapp);
// Web application is configured and ready
} else {
System.err.println("Configuration was aborted");
}
} catch (Exception e) {
System.err.println("Configuration failed: " + e.getMessage());
}import org.eclipse.jetty.ee10.webapp.*;
public class SecurityConfiguration extends AbstractConfiguration {
public SecurityConfiguration() {
super(new Builder()
.enabledByDefault(true)
.protect("java.security.", "javax.crypto.")
.hide("org.eclipse.jetty.security.internal.")
.addDependencies(WebXmlConfiguration.class)
);
}
@Override
public void configure(WebAppContext context) throws Exception {
// Apply security-specific configuration
context.getSecurityHandler().setAuthenticator(new CustomAuthenticator());
}
}Configuration operations can throw exceptions during the lifecycle phases:
Exception - General configuration errors during any lifecycle methodIllegalStateException - Invalid configuration state or circular dependenciesClassNotFoundException - Missing configuration class when using string-based configurationIOException - I/O errors when processing files or resourcesCommon error scenarios:
Configurations are discovered using Java's ServiceLoader mechanism:
// META-INF/services/org.eclipse.jetty.ee10.webapp.Configuration
org.eclipse.jetty.ee10.webapp.WebXmlConfiguration
org.eclipse.jetty.ee10.webapp.MetaInfConfiguration
org.eclipse.jetty.ee10.webapp.FragmentConfiguration
// ... other configurations
// Automatic discovery
ServiceLoader<Configuration> loader = ServiceLoader.load(Configuration.class);
for (Configuration config : loader) {
// Use discovered configurations
}Install with Tessl CLI
npx tessl i tessl/maven-org-eclipse-jetty-ee10--jetty-ee10-webapp