Jetty web application support library providing comprehensive webapp deployment, configuration, and class loading capabilities
—
Jetty WebApp provides fine-grained control over class visibility and loading delegation through pattern-based class matchers. This system allows precise control over which classes are loaded by the system classloader, server classloader, or webapp classloader.
Pattern-based matcher for controlling class visibility and loading delegation.
/**
* Pattern matcher for classes based on package, location, and module patterns.
* Supports inclusion and exclusion patterns with precedence rules.
*/
public class ClassMatcher extends AbstractSet<String> {
/**
* Create empty class matcher
*/
public ClassMatcher();
/**
* Copy constructor
*/
public ClassMatcher(ClassMatcher patterns);
/**
* Create with initial patterns
*/
public ClassMatcher(String... patterns);
/**
* Create with single pattern
*/
public ClassMatcher(String pattern);
}Methods for adding and managing class patterns.
/**
* Include class patterns (positive match)
*/
public boolean include(String name);
public boolean include(String... name);
/**
* Exclude class patterns (negative match)
*/
public boolean exclude(String name);
public boolean exclude(String... name);
/**
* Add patterns (defaults to inclusion)
*/
public boolean add(String pattern);
public boolean add(String... pattern);
/**
* Get all patterns
*/
public String[] getPatterns();
/**
* Get inclusion patterns only
*/
public String[] getInclusions();
/**
* Get exclusion patterns only
*/
public String[] getExclusions();Usage Examples:
ClassMatcher matcher = new ClassMatcher();
// Include patterns
matcher.include("com.mycompany.");
matcher.include("org.apache.commons.");
// Exclude patterns
matcher.exclude("com.mycompany.internal.");
matcher.exclude("org.apache.commons.logging.");
// Add multiple patterns
matcher.add("javax.servlet.", "jakarta.servlet.");Methods for testing class names against patterns.
/**
* Test if class name matches patterns
*/
public boolean match(String name);
/**
* Test if class matches patterns
*/
public boolean match(Class<?> clazz);
/**
* Test if class name and URL match patterns
*/
public boolean match(String name, URL url);Usage Examples:
// Test class names
if (matcher.match("com.mycompany.MyClass")) {
// Class matches inclusion patterns
}
// Test class objects
if (matcher.match(String.class)) {
// java.lang.String matches patterns
}
// Test with URL context
URL jarUrl = new URL("file:/path/to/lib.jar");
if (matcher.match("com.example.Service", jarUrl)) {
// Class from specific JAR matches
}Information about individual pattern entries and specialized implementations.
/**
* Represents a single pattern entry with inclusion/exclusion flag
*/
public static class Entry {
/**
* Get the pattern string
*/
public String getPattern();
/**
* Get the pattern name (same as pattern)
*/
public String getName();
/**
* Check if this is an inclusive pattern
*/
public boolean isInclusive();
/**
* Test if this entry matches a class name
*/
public boolean match(String name);
/**
* Test if this entry matches a class and URL
*/
public boolean match(String name, URL url);
}
/**
* Entry for package-based patterns
*/
public static class PackageEntry extends Entry {
public PackageEntry(String pattern, boolean inclusive);
}
/**
* Entry for exact class name patterns
*/
public static class ClassEntry extends Entry {
public ClassEntry(String pattern, boolean inclusive);
}
/**
* Entry for location-based patterns (JAR files, directories)
*/
public static class LocationEntry extends Entry {
public LocationEntry(String pattern, boolean inclusive);
}
/**
* Entry for module-based patterns (Java 9+ modules)
*/
public static class ModuleEntry extends Entry {
public ModuleEntry(String pattern, boolean inclusive);
}// Package prefix matching
"com.mycompany." // Matches com.mycompany.* packages
"org.eclipse.jetty." // Matches org.eclipse.jetty.* packages
// Exact class matching
"com.mycompany.MyClass" // Matches exact class only
// Wildcard matching
"com.mycompany.*" // Same as "com.mycompany."
"*.internal.*" // Matches any package containing "internal"// Exclusion patterns (prefix with '-')
"-com.mycompany.internal." // Exclude internal packages
"-org.eclipse.jetty.util.log." // Exclude logging utilities
// Location-based patterns
"file:/path/to/specific.jar" // Match classes from specific JAR
"file:/lib/" // Match classes from lib directory
// Module-based patterns (Java 9+)
"java.base/" // Match classes from java.base module
"java.logging/" // Match classes from java.logging moduleClassMatcher matcher = new ClassMatcher();
// More specific patterns take precedence
matcher.include("com.mycompany."); // Include mycompany packages
matcher.exclude("com.mycompany.internal."); // But exclude internal
matcher.include("com.mycompany.internal.api."); // Except API classes
// Test precedence
matcher.match("com.mycompany.Service"); // true (included)
matcher.match("com.mycompany.internal.Util"); // false (excluded)
matcher.match("com.mycompany.internal.api.Service"); // true (re-included)WebAppContext uses ClassMatcher for system and server class controls.
// WebAppContext methods using ClassMatcher
public ClassMatcher getSystemClassMatcher();
public void setSystemClassMatcher(ClassMatcher systemClasses);
public void addSystemClassMatcher(ClassMatcher systemClasses);
public ClassMatcher getServerClassMatcher();
public void setServerClassMatcher(ClassMatcher serverClasses);
public void addServerClassMatcher(ClassMatcher serverClasses);Usage Examples:
WebAppContext webapp = new WebAppContext();
// Set system classes (loaded by system classloader)
ClassMatcher systemClasses = new ClassMatcher();
systemClasses.include("java.", "javax.", "jakarta.");
systemClasses.include("org.xml.", "org.w3c.");
webapp.setSystemClassMatcher(systemClasses);
// Set server classes (hidden from webapp)
ClassMatcher serverClasses = new ClassMatcher();
serverClasses.include("org.eclipse.jetty.");
serverClasses.exclude("org.eclipse.jetty.servlet.listener.");
webapp.setServerClassMatcher(serverClasses);Configurations can contribute class visibility patterns.
// Configuration interface methods
default ClassMatcher getSystemClasses() { return null; }
default ClassMatcher getServerClasses() { return null; }
// AbstractConfiguration protected methods
protected void protect(String... classes); // Add to system classes
protected void hide(String... classes); // Add to server classes
protected void expose(String... classes); // Remove from server classes
protected void protectAndExpose(String... classes); // Add to system, remove from serverUsage Examples:
public class MyConfiguration extends AbstractConfiguration {
public MyConfiguration() {
// Protect shared libraries
protect("com.mycompany.shared.");
// Hide internal server classes
hide("com.mycompany.server.internal.");
// Expose specific server utilities to webapps
expose("com.mycompany.server.util.StringUtils");
}
}Classes loaded by the system classloader (not isolated per webapp).
// Java platform classes
"java."
"javax."
"jakarta."
"sun."
"com.sun."
// XML processing
"org.xml."
"org.w3c."
// Other system classes
"org.slf4j." // Logging facade
"org.apache.commons.logging." // Commons loggingClasses hidden from webapps (loaded by server classloader).
// Jetty server classes
"org.eclipse.jetty."
"-org.eclipse.jetty.servlet.listener." // Except servlet listeners
"-org.eclipse.jetty.util.log." // Except webapp logging
// Server implementation classes
"org.mortbay."
"org.apache.jasper." // JSP compiler (when present)// Create webapp with custom class isolation
WebAppContext webapp = new WebAppContext();
// System classes: shared across all webapps
ClassMatcher systemClasses = new ClassMatcher();
systemClasses.include("java.", "javax.", "jakarta.");
systemClasses.include("com.mycompany.shared.");
webapp.setSystemClassMatcher(systemClasses);
// Server classes: hidden from webapps
ClassMatcher serverClasses = new ClassMatcher();
serverClasses.include("org.eclipse.jetty.");
serverClasses.include("com.mycompany.server.");
serverClasses.exclude("com.mycompany.server.api."); // Expose API
webapp.setServerClassMatcher(serverClasses);// Development: expose more server classes for debugging
if (isDevelopmentMode()) {
ClassMatcher serverClasses = webapp.getServerClassMatcher();
serverClasses.exclude("org.eclipse.jetty.util.log.");
serverClasses.exclude("org.eclipse.jetty.server.handler.DebugHandler");
}
// Production: strict isolation
if (isProductionMode()) {
ClassMatcher serverClasses = new ClassMatcher();
serverClasses.include("org.eclipse.jetty.");
serverClasses.include("com.mycompany.server.");
// No exclusions - strict hiding
webapp.setServerClassMatcher(serverClasses);
}// Isolate tenant-specific classes
public class TenantConfiguration extends AbstractConfiguration {
private final String tenantId;
public TenantConfiguration(String tenantId) {
this.tenantId = tenantId;
// Each tenant gets their own version of these classes
hide("com.myapp.tenant." + tenantId + ".");
// But shared utilities are system classes
protect("com.myapp.shared.");
}
}
// Apply to webapp
webapp.addConfiguration(new TenantConfiguration("tenant1"));// Isolate specific library versions per webapp
ClassMatcher serverClasses = webapp.getServerClassMatcher();
// Hide server's Jackson version, let webapp use its own
serverClasses.include("com.fasterxml.jackson.");
// Hide server's Spring version
serverClasses.include("org.springframework.");
// But expose specific server utilities
serverClasses.exclude("com.mycompany.server.jackson.CustomModule");// Update patterns at runtime (before webapp start)
ClassMatcher matcher = webapp.getSystemClassMatcher();
// Add patterns dynamically
Properties config = loadConfiguration();
for (String pattern : config.getProperty("system.classes", "").split(",")) {
if (!pattern.trim().isEmpty()) {
matcher.include(pattern.trim());
}
}
// Remove patterns
for (String pattern : config.getProperty("exclude.system.classes", "").split(",")) {
if (!pattern.trim().isEmpty()) {
matcher.exclude(pattern.trim());
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-eclipse-jetty--jetty-webapp