CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-eclipse-jetty--jetty-plus

JNDI support for Eclipse Jetty web server including dependency injection, lifecycle management, JNDI resource binding, and database-backed security services

Pending
Overview
Eval results
Files

jndi-integration.mddocs/

JNDI Resource Binding

Comprehensive JNDI naming and resource binding capabilities supporting environment entries, resources, links, and transactions with full webapp context integration and scope management.

Capabilities

Base JNDI Functionality

Core abstract base class for all JNDI-related entities with scope management and ENC (Environment Naming Context) binding capabilities.

abstract class NamingEntry {
    // Constants
    static final String __contextName = "__";
    
    // Protected constructor - use concrete subclasses
    protected NamingEntry(Object scope, String jndiName, Object objectToBind) throws NamingException;
    
    // Bind to java:comp/env namespace
    void bindToENC(String localName) throws NamingException;
    
    // Unbind from java:comp/env namespace
    void unbindENC();
    
    // Complete release and cleanup
    void release();
    
    // Query methods
    String getJndiName();
    String getJndiNameInScope();
    String getNamingEntryNameInScope();
}

JNDI Utility Operations

Comprehensive utility class providing static methods for JNDI operations, NamingEntry management, and context manipulation with scope awareness.

class NamingEntryUtil {
    // Link name in webapp's java:comp/env to global JNDI name
    static boolean bindToENC(Object scope, String asName, String mappedName) throws NamingException;
    
    // Find NamingEntry in specific scope
    static NamingEntry lookupNamingEntry(Object scope, String jndiName) throws NamingException;
    
    // Lookup object in scope
    static Object lookup(Object scope, String jndiName) throws NamingException;
    
    // Get all NamingEntries of specific type in scope
    static <T> List<? extends T> lookupNamingEntries(Object scope, Class<T> clazz) throws NamingException;
    
    // Name creation utilities
    static Name makeNamingEntryName(NameParser parser, NamingEntry namingEntry) throws NamingException;
    static Name makeNamingEntryName(NameParser parser, String jndiName) throws NamingException;
    
    // Scope management
    static Name getNameForScope(Object scope);
    static Context getContextForScope(Object scope) throws NamingException;
    static void destroyContextForScope(Object scope) throws NamingException;
}

Usage Example:

// Bind a local ENC name to a global JNDI name
boolean bound = NamingEntryUtil.bindToENC(webappContext, "jdbc/LocalDB", "java:/comp/env/jdbc/GlobalDB");

// Lookup resources by type
List<? extends Resource> resources = NamingEntryUtil.lookupNamingEntries(webappContext, Resource.class);

// Get context for scope operations
Context scopeContext = NamingEntryUtil.getContextForScope(webappContext);

Environment Entries

Environment entries for binding configuration values and simple objects to JNDI with web.xml override capabilities.

class EnvEntry extends NamingEntry {
    // Constructors with scope
    EnvEntry(Object scope, String jndiName, Object objToBind, boolean overrideWebXml) throws NamingException;
    
    // Global constructors
    EnvEntry(String jndiName, Object objToBind, boolean overrideWebXml) throws NamingException;
    EnvEntry(String jndiName, Object objToBind) throws NamingException;
    
    // Check if this entry overrides web.xml settings
    boolean isOverrideWebXml();
}

Usage Example:

// Create environment entries with different scopes
EnvEntry maxConnections = new EnvEntry(webapp, "maxConnections", 100, true);
EnvEntry debugMode = new EnvEntry("debugMode", false);

// Environment entry automatically available in JNDI
InitialContext ctx = new InitialContext();
Integer maxConn = (Integer) ctx.lookup("java:comp/env/maxConnections");
Boolean debug = (Boolean) ctx.lookup("java:comp/env/debugMode");

Resource Binding

Resource binding for complex objects like DataSources, JMS resources, and other enterprise resources with automatic JNDI registration.

class Resource extends NamingEntry {
    // Scoped resource binding
    Resource(Object scope, String jndiName, Object objToBind) throws NamingException;
    
    // Global resource binding
    Resource(String jndiName, Object objToBind) throws NamingException;
}

Usage Example:

// Bind various types of resources
DataSource dataSource = createDataSource();
Resource dsResource = new Resource(webapp, "jdbc/MyDB", dataSource);

ConnectionFactory jmsFactory = createJMSConnectionFactory();
Resource jmsResource = new Resource("jms/MyConnectionFactory", jmsFactory);

// Resources automatically available via JNDI lookup
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/MyDB");
ConnectionFactory cf = (ConnectionFactory) ctx.lookup("java:comp/env/jms/MyConnectionFactory");

JNDI Links

Create links between JNDI names for aliasing and indirection, supporting complex naming hierarchies and resource sharing patterns.

class Link extends NamingEntry {
    // Scoped link creation
    Link(Object scope, String jndiName, String link) throws NamingException;
    
    // Global link creation
    Link(String jndiName, String link) throws NamingException;
    
    // Get target link destination
    String getLink();
    
    // Override - Links cannot be bound to ENC directly
    void bindToENC(String localName) throws NamingException; // Throws UnsupportedOperationException
}

Usage Example:

// Create links for resource aliasing
Link dbLink = new Link(webapp, "jdbc/PrimaryDB", "jdbc/ProductionDatabase");
Link testDbLink = new Link("jdbc/TestDB", "jdbc/DevelopmentDatabase");

// Links provide indirection
InitialContext ctx = new InitialContext();
DataSource primary = (DataSource) ctx.lookup("java:comp/env/jdbc/PrimaryDB");
// Actually resolves to jdbc/ProductionDatabase

Transaction Integration

JTA UserTransaction implementation with ENC binding support for transaction management in enterprise applications.

class Transaction extends NamingEntry {
    // Constants
    static final String USER_TRANSACTION = "UserTransaction";
    
    // Protected constructor for direct use
    protected Transaction(String scope, Object entry) throws NamingException;
    
    // Reference-based constructor
    Transaction(String scope, Reference userTransactionRef) throws NamingException;
    
    // Static utility for binding UserTransaction to ENC
    static void bindTransactionToENC(String scope) throws NamingException;
    
    // Override to allow additional UserTransaction bindings
    void bindToENC(String localName) throws NamingException;
    
    // Custom unbind behavior
    void unbindENC();
}

Usage Example:

// Bind UserTransaction for webapp
Transaction.bindTransactionToENC(webapp.toString());

// Access transaction in application code
InitialContext ctx = new InitialContext();
UserTransaction utx = (UserTransaction) ctx.lookup("java:comp/UserTransaction");

// Use JTA transactions
utx.begin();
try {
    // Transactional operations
    performDatabaseOperations();
    utx.commit();
} catch (Exception e) {
    utx.rollback();
    throw e;
}

DataSource Resource Management

Proper cleanup and shutdown support for DataSource resources, especially important for connection pools and embedded databases.

class DataSourceCloser implements Destroyable {
    // Basic constructor
    DataSourceCloser(DataSource datasource);
    
    // Constructor with shutdown SQL
    DataSourceCloser(DataSource datasource, String shutdownSQL);
    
    // Implement Destroyable interface
    void destroy();
}

Usage Example:

// Set up DataSource with proper cleanup
DataSource dataSource = createAtomikosDataSource();
DataSourceCloser closer = new DataSourceCloser(dataSource, "SHUTDOWN");

// Register for cleanup (typically with webapp lifecycle)
webapp.addBean(closer);

// Automatic cleanup on webapp shutdown
// closer.destroy() will be called, executing shutdown SQL if provided

Integration Patterns

Complete JNDI Configuration

// Set up comprehensive JNDI environment for webapp
WebAppContext webapp = new WebAppContext();

// Database resources
DataSource primaryDB = createPrimaryDataSource();
DataSource replicaDB = createReplicaDataSource();
Resource primary = new Resource(webapp, "jdbc/PrimaryDB", primaryDB);
Resource replica = new Resource(webapp, "jdbc/ReplicaDB", replicaDB);

// Environment configuration
EnvEntry maxConnections = new EnvEntry(webapp, "maxConnections", 50, true);
EnvEntry timeout = new EnvEntry(webapp, "timeout", 30000, false);

// Create convenient aliases
Link mainDB = new Link(webapp, "jdbc/MainDB", "jdbc/PrimaryDB");
Link backupDB = new Link(webapp, "jdbc/BackupDB", "jdbc/ReplicaDB");

// JMS resources
ConnectionFactory jmsFactory = createJMSConnectionFactory();
Resource jms = new Resource(webapp, "jms/ConnectionFactory", jmsFactory);

// Transaction support
Transaction.bindTransactionToENC(webapp.toString());

// Cleanup management
DataSourceCloser primaryCloser = new DataSourceCloser(primaryDB);
DataSourceCloser replicaCloser = new DataSourceCloser(replicaDB, "SHUTDOWN IMMEDIATELY");
webapp.addBean(primaryCloser);
webapp.addBean(replicaCloser);

Dynamic Resource Discovery

// Discover all resources bound in a webapp context
List<? extends Resource> resources = NamingEntryUtil.lookupNamingEntries(webapp, Resource.class);
List<? extends EnvEntry> envEntries = NamingEntryUtil.lookupNamingEntries(webapp, EnvEntry.class);
List<? extends Link> links = NamingEntryUtil.lookupNamingEntries(webapp, Link.class);

// Process each type of resource
for (Resource resource : resources) {
    System.out.println("Resource: " + resource.getJndiName());
    Object boundObject = NamingEntryUtil.lookup(webapp, resource.getJndiName());
    System.out.println("Type: " + boundObject.getClass());
}

for (EnvEntry entry : envEntries) {
    System.out.println("EnvEntry: " + entry.getJndiName() + 
                      " (overrides web.xml: " + entry.isOverrideWebXml() + ")");
}

for (Link link : links) {
    System.out.println("Link: " + link.getJndiName() + " -> " + link.getLink());
}

Scope-based Resource Management

// Different scoping strategies for resources

// 1. Global scope resources (available to all webapps)
Resource globalDB = new Resource("jdbc/GlobalDB", globalDataSource);
EnvEntry globalConfig = new EnvEntry("globalSetting", "production");

// 2. Webapp-scoped resources (available only to specific webapp)
Resource webappDB = new Resource(webapp, "jdbc/WebappDB", webappDataSource);
EnvEntry webappConfig = new EnvEntry(webapp, "webappSetting", "enabled", true);

// 3. Context management
Context globalContext = NamingEntryUtil.getContextForScope(null);
Context webappContext = NamingEntryUtil.getContextForScope(webapp);

// 4. Cleanup on webapp shutdown
webapp.addEventListener(new LifeCycle.Listener() {
    @Override
    public void lifeCycleStopping(LifeCycle event) {
        try {
            NamingEntryUtil.destroyContextForScope(webapp);
        } catch (NamingException e) {
            LOG.warn("Error destroying JNDI context", e);
        }
    }
});

Error Handling and Best Practices

Exception Handling

try {
    // Resource binding with error handling
    Resource resource = new Resource(webapp, "jdbc/MyDB", dataSource);
    
    // Verify binding worked
    Object lookup = NamingEntryUtil.lookup(webapp, "jdbc/MyDB");
    if (lookup == null) {
        throw new IllegalStateException("Resource binding failed");
    }
    
} catch (NamingException e) {
    LOG.error("JNDI binding failed for jdbc/MyDB", e);
    // Fallback strategy or re-throw
}

Resource Lifecycle Management

// Proper resource lifecycle with cleanup
DataSource dataSource = null;
Resource resource = null;
try {
    dataSource = createDataSource();
    resource = new Resource(webapp, "jdbc/MyDB", dataSource);
    
    // Use resource...
    
} finally {
    // Cleanup in reverse order
    if (resource != null) {
        try {
            resource.release();
        } catch (Exception e) {
            LOG.warn("Error releasing JNDI resource", e);
        }
    }
    
    if (dataSource instanceof Closeable) {
        try {
            ((Closeable) dataSource).close();
        } catch (Exception e) {
            LOG.warn("Error closing DataSource", e);
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-eclipse-jetty--jetty-plus

docs

annotation-support.md

index.md

jndi-integration.md

security-services.md

tile.json