0
# JNDI Resource Binding
1
2
Comprehensive JNDI naming and resource binding capabilities supporting environment entries, resources, links, and transactions with full webapp context integration and scope management.
3
4
## Capabilities
5
6
### Base JNDI Functionality
7
8
Core abstract base class for all JNDI-related entities with scope management and ENC (Environment Naming Context) binding capabilities.
9
10
```java { .api }
11
abstract class NamingEntry {
12
// Constants
13
static final String __contextName = "__";
14
15
// Protected constructor - use concrete subclasses
16
protected NamingEntry(Object scope, String jndiName, Object objectToBind) throws NamingException;
17
18
// Bind to java:comp/env namespace
19
void bindToENC(String localName) throws NamingException;
20
21
// Unbind from java:comp/env namespace
22
void unbindENC();
23
24
// Complete release and cleanup
25
void release();
26
27
// Query methods
28
String getJndiName();
29
String getJndiNameInScope();
30
String getNamingEntryNameInScope();
31
}
32
```
33
34
### JNDI Utility Operations
35
36
Comprehensive utility class providing static methods for JNDI operations, NamingEntry management, and context manipulation with scope awareness.
37
38
```java { .api }
39
class NamingEntryUtil {
40
// Link name in webapp's java:comp/env to global JNDI name
41
static boolean bindToENC(Object scope, String asName, String mappedName) throws NamingException;
42
43
// Find NamingEntry in specific scope
44
static NamingEntry lookupNamingEntry(Object scope, String jndiName) throws NamingException;
45
46
// Lookup object in scope
47
static Object lookup(Object scope, String jndiName) throws NamingException;
48
49
// Get all NamingEntries of specific type in scope
50
static <T> List<? extends T> lookupNamingEntries(Object scope, Class<T> clazz) throws NamingException;
51
52
// Name creation utilities
53
static Name makeNamingEntryName(NameParser parser, NamingEntry namingEntry) throws NamingException;
54
static Name makeNamingEntryName(NameParser parser, String jndiName) throws NamingException;
55
56
// Scope management
57
static Name getNameForScope(Object scope);
58
static Context getContextForScope(Object scope) throws NamingException;
59
static void destroyContextForScope(Object scope) throws NamingException;
60
}
61
```
62
63
**Usage Example:**
64
```java
65
// Bind a local ENC name to a global JNDI name
66
boolean bound = NamingEntryUtil.bindToENC(webappContext, "jdbc/LocalDB", "java:/comp/env/jdbc/GlobalDB");
67
68
// Lookup resources by type
69
List<? extends Resource> resources = NamingEntryUtil.lookupNamingEntries(webappContext, Resource.class);
70
71
// Get context for scope operations
72
Context scopeContext = NamingEntryUtil.getContextForScope(webappContext);
73
```
74
75
### Environment Entries
76
77
Environment entries for binding configuration values and simple objects to JNDI with web.xml override capabilities.
78
79
```java { .api }
80
class EnvEntry extends NamingEntry {
81
// Constructors with scope
82
EnvEntry(Object scope, String jndiName, Object objToBind, boolean overrideWebXml) throws NamingException;
83
84
// Global constructors
85
EnvEntry(String jndiName, Object objToBind, boolean overrideWebXml) throws NamingException;
86
EnvEntry(String jndiName, Object objToBind) throws NamingException;
87
88
// Check if this entry overrides web.xml settings
89
boolean isOverrideWebXml();
90
}
91
```
92
93
**Usage Example:**
94
```java
95
// Create environment entries with different scopes
96
EnvEntry maxConnections = new EnvEntry(webapp, "maxConnections", 100, true);
97
EnvEntry debugMode = new EnvEntry("debugMode", false);
98
99
// Environment entry automatically available in JNDI
100
InitialContext ctx = new InitialContext();
101
Integer maxConn = (Integer) ctx.lookup("java:comp/env/maxConnections");
102
Boolean debug = (Boolean) ctx.lookup("java:comp/env/debugMode");
103
```
104
105
### Resource Binding
106
107
Resource binding for complex objects like DataSources, JMS resources, and other enterprise resources with automatic JNDI registration.
108
109
```java { .api }
110
class Resource extends NamingEntry {
111
// Scoped resource binding
112
Resource(Object scope, String jndiName, Object objToBind) throws NamingException;
113
114
// Global resource binding
115
Resource(String jndiName, Object objToBind) throws NamingException;
116
}
117
```
118
119
**Usage Example:**
120
```java
121
// Bind various types of resources
122
DataSource dataSource = createDataSource();
123
Resource dsResource = new Resource(webapp, "jdbc/MyDB", dataSource);
124
125
ConnectionFactory jmsFactory = createJMSConnectionFactory();
126
Resource jmsResource = new Resource("jms/MyConnectionFactory", jmsFactory);
127
128
// Resources automatically available via JNDI lookup
129
InitialContext ctx = new InitialContext();
130
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/MyDB");
131
ConnectionFactory cf = (ConnectionFactory) ctx.lookup("java:comp/env/jms/MyConnectionFactory");
132
```
133
134
### JNDI Links
135
136
Create links between JNDI names for aliasing and indirection, supporting complex naming hierarchies and resource sharing patterns.
137
138
```java { .api }
139
class Link extends NamingEntry {
140
// Scoped link creation
141
Link(Object scope, String jndiName, String link) throws NamingException;
142
143
// Global link creation
144
Link(String jndiName, String link) throws NamingException;
145
146
// Get target link destination
147
String getLink();
148
149
// Override - Links cannot be bound to ENC directly
150
void bindToENC(String localName) throws NamingException; // Throws UnsupportedOperationException
151
}
152
```
153
154
**Usage Example:**
155
```java
156
// Create links for resource aliasing
157
Link dbLink = new Link(webapp, "jdbc/PrimaryDB", "jdbc/ProductionDatabase");
158
Link testDbLink = new Link("jdbc/TestDB", "jdbc/DevelopmentDatabase");
159
160
// Links provide indirection
161
InitialContext ctx = new InitialContext();
162
DataSource primary = (DataSource) ctx.lookup("java:comp/env/jdbc/PrimaryDB");
163
// Actually resolves to jdbc/ProductionDatabase
164
```
165
166
### Transaction Integration
167
168
JTA UserTransaction implementation with ENC binding support for transaction management in enterprise applications.
169
170
```java { .api }
171
class Transaction extends NamingEntry {
172
// Constants
173
static final String USER_TRANSACTION = "UserTransaction";
174
175
// Protected constructor for direct use
176
protected Transaction(String scope, Object entry) throws NamingException;
177
178
// Reference-based constructor
179
Transaction(String scope, Reference userTransactionRef) throws NamingException;
180
181
// Static utility for binding UserTransaction to ENC
182
static void bindTransactionToENC(String scope) throws NamingException;
183
184
// Override to allow additional UserTransaction bindings
185
void bindToENC(String localName) throws NamingException;
186
187
// Custom unbind behavior
188
void unbindENC();
189
}
190
```
191
192
**Usage Example:**
193
```java
194
// Bind UserTransaction for webapp
195
Transaction.bindTransactionToENC(webapp.toString());
196
197
// Access transaction in application code
198
InitialContext ctx = new InitialContext();
199
UserTransaction utx = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
200
201
// Use JTA transactions
202
utx.begin();
203
try {
204
// Transactional operations
205
performDatabaseOperations();
206
utx.commit();
207
} catch (Exception e) {
208
utx.rollback();
209
throw e;
210
}
211
```
212
213
### DataSource Resource Management
214
215
Proper cleanup and shutdown support for DataSource resources, especially important for connection pools and embedded databases.
216
217
```java { .api }
218
class DataSourceCloser implements Destroyable {
219
// Basic constructor
220
DataSourceCloser(DataSource datasource);
221
222
// Constructor with shutdown SQL
223
DataSourceCloser(DataSource datasource, String shutdownSQL);
224
225
// Implement Destroyable interface
226
void destroy();
227
}
228
```
229
230
**Usage Example:**
231
```java
232
// Set up DataSource with proper cleanup
233
DataSource dataSource = createAtomikosDataSource();
234
DataSourceCloser closer = new DataSourceCloser(dataSource, "SHUTDOWN");
235
236
// Register for cleanup (typically with webapp lifecycle)
237
webapp.addBean(closer);
238
239
// Automatic cleanup on webapp shutdown
240
// closer.destroy() will be called, executing shutdown SQL if provided
241
```
242
243
## Integration Patterns
244
245
### Complete JNDI Configuration
246
247
```java
248
// Set up comprehensive JNDI environment for webapp
249
WebAppContext webapp = new WebAppContext();
250
251
// Database resources
252
DataSource primaryDB = createPrimaryDataSource();
253
DataSource replicaDB = createReplicaDataSource();
254
Resource primary = new Resource(webapp, "jdbc/PrimaryDB", primaryDB);
255
Resource replica = new Resource(webapp, "jdbc/ReplicaDB", replicaDB);
256
257
// Environment configuration
258
EnvEntry maxConnections = new EnvEntry(webapp, "maxConnections", 50, true);
259
EnvEntry timeout = new EnvEntry(webapp, "timeout", 30000, false);
260
261
// Create convenient aliases
262
Link mainDB = new Link(webapp, "jdbc/MainDB", "jdbc/PrimaryDB");
263
Link backupDB = new Link(webapp, "jdbc/BackupDB", "jdbc/ReplicaDB");
264
265
// JMS resources
266
ConnectionFactory jmsFactory = createJMSConnectionFactory();
267
Resource jms = new Resource(webapp, "jms/ConnectionFactory", jmsFactory);
268
269
// Transaction support
270
Transaction.bindTransactionToENC(webapp.toString());
271
272
// Cleanup management
273
DataSourceCloser primaryCloser = new DataSourceCloser(primaryDB);
274
DataSourceCloser replicaCloser = new DataSourceCloser(replicaDB, "SHUTDOWN IMMEDIATELY");
275
webapp.addBean(primaryCloser);
276
webapp.addBean(replicaCloser);
277
```
278
279
### Dynamic Resource Discovery
280
281
```java
282
// Discover all resources bound in a webapp context
283
List<? extends Resource> resources = NamingEntryUtil.lookupNamingEntries(webapp, Resource.class);
284
List<? extends EnvEntry> envEntries = NamingEntryUtil.lookupNamingEntries(webapp, EnvEntry.class);
285
List<? extends Link> links = NamingEntryUtil.lookupNamingEntries(webapp, Link.class);
286
287
// Process each type of resource
288
for (Resource resource : resources) {
289
System.out.println("Resource: " + resource.getJndiName());
290
Object boundObject = NamingEntryUtil.lookup(webapp, resource.getJndiName());
291
System.out.println("Type: " + boundObject.getClass());
292
}
293
294
for (EnvEntry entry : envEntries) {
295
System.out.println("EnvEntry: " + entry.getJndiName() +
296
" (overrides web.xml: " + entry.isOverrideWebXml() + ")");
297
}
298
299
for (Link link : links) {
300
System.out.println("Link: " + link.getJndiName() + " -> " + link.getLink());
301
}
302
```
303
304
### Scope-based Resource Management
305
306
```java
307
// Different scoping strategies for resources
308
309
// 1. Global scope resources (available to all webapps)
310
Resource globalDB = new Resource("jdbc/GlobalDB", globalDataSource);
311
EnvEntry globalConfig = new EnvEntry("globalSetting", "production");
312
313
// 2. Webapp-scoped resources (available only to specific webapp)
314
Resource webappDB = new Resource(webapp, "jdbc/WebappDB", webappDataSource);
315
EnvEntry webappConfig = new EnvEntry(webapp, "webappSetting", "enabled", true);
316
317
// 3. Context management
318
Context globalContext = NamingEntryUtil.getContextForScope(null);
319
Context webappContext = NamingEntryUtil.getContextForScope(webapp);
320
321
// 4. Cleanup on webapp shutdown
322
webapp.addEventListener(new LifeCycle.Listener() {
323
@Override
324
public void lifeCycleStopping(LifeCycle event) {
325
try {
326
NamingEntryUtil.destroyContextForScope(webapp);
327
} catch (NamingException e) {
328
LOG.warn("Error destroying JNDI context", e);
329
}
330
}
331
});
332
```
333
334
## Error Handling and Best Practices
335
336
### Exception Handling
337
338
```java
339
try {
340
// Resource binding with error handling
341
Resource resource = new Resource(webapp, "jdbc/MyDB", dataSource);
342
343
// Verify binding worked
344
Object lookup = NamingEntryUtil.lookup(webapp, "jdbc/MyDB");
345
if (lookup == null) {
346
throw new IllegalStateException("Resource binding failed");
347
}
348
349
} catch (NamingException e) {
350
LOG.error("JNDI binding failed for jdbc/MyDB", e);
351
// Fallback strategy or re-throw
352
}
353
```
354
355
### Resource Lifecycle Management
356
357
```java
358
// Proper resource lifecycle with cleanup
359
DataSource dataSource = null;
360
Resource resource = null;
361
try {
362
dataSource = createDataSource();
363
resource = new Resource(webapp, "jdbc/MyDB", dataSource);
364
365
// Use resource...
366
367
} finally {
368
// Cleanup in reverse order
369
if (resource != null) {
370
try {
371
resource.release();
372
} catch (Exception e) {
373
LOG.warn("Error releasing JNDI resource", e);
374
}
375
}
376
377
if (dataSource instanceof Closeable) {
378
try {
379
((Closeable) dataSource).close();
380
} catch (Exception e) {
381
LOG.warn("Error closing DataSource", e);
382
}
383
}
384
}
385
```