Contexts

Contexts provide a hierarchical structure to JNDI names, and composite names group together related names. The initial context provides a top-level view of the namespace and any sub-contexts reflect the hierarchical composite name structure.

Listing Contexts

The namespace represents contexts as names, and you can look these up just like any other name. You can obtain a listing of the names in a context by using Context.list(). This method provides a list of name and class bindings as a javax.naming.NamingEnumeration, where each element in the enumeration is a javax.naming.NameClassPair object. Listing 3.5 shows a simple program to list the names and classes for the example sams sub context.

Listing 3.5. Full Text of JNDIListSAMS.java
 1: import javax.naming.*;
 2: public class JNDIListSAMS
 3: {
 4:     public static void main(String[] args)
 5:     {
 6:         try {
 7:             Context ctx = new InitialContext();
 8:             NamingEnumeration list = ctx.list("sams");
 9:             while (list.hasMore()) {
10:                 NameClassPair item = (NameClassPair)list.next();
11:                 String cl = item.getClassName();
12:                 String name = item.getName();
13:                 System.out.println(cl+" - "+name);
14:             }
15:         }
16:         catch (NamingException ex) {
17:             System.out.println (ex);
18:             System.exit(1);
19:         }
20:     }
21: }
						

You must run the JNDIBind program from Listing 3.1 before running this program; otherwise, the “sams” sub context will not exist. Running the program in Listing 3.5 will produce a single line of output:

java.lang.String – book

The parameter to the list() method defines the name of the context to list. If this is the empty string, the method lists the current context.

If the initial context of the J2EE RI namespace is listed, you must have the J2EE RI classes in your search path; otherwise, you will get an org.omg.CORBA.BAD_PARAM exception caused by another CORBA exception:

org.omg.CORBA.MARSHAL: Unable to read value from underlying bridge : Serializable
 readObject method failed internally minor code: 1398079699 completed: Maybe

Don't believe the completed: Maybe tagged on to the end of the error message. It didn't complete.

The easiest solution to this problem is to run the setenv script in the bin directory of J2EE RI. This script creates a variable CPATH that you can use as the CLASSPATH for running J2EE RI client programs.

Under Windows use

%J2EE_HOME%insetenv
java –classpath .;%CPATH% JNDIList

Under Linux and Unix use

$J2EE_HOME/bin/setenv
java –classpath .:$CPATH JNDIList

The CD-ROM accompanying this book includes the JNDIList program, which is the same as the program in Listing 3.5 but without the parameter to the list() method.

The list() method returns the name and the bound object's classname, but not the object itself. It is a lightweight interface designed for browsing the namespace.

A second method, called Context.listBindings(), retrieves the object itself. The listBindings() method returns a NamingEnumeration, where each element is of type javax.naming.Binding. Access methods in the Binding class support retrieval of the information of the bound object. Listing 3.6 shows a simple recursive tree-walking program that is a useful diagnostic tool for examining JNDI namespaces.

Listing 3.6. Full Text of JNDITree.java
 1: import javax.naming.*;
 2: public class JNDITree
 3: {
 4:     public static void main(String[] args) {
 5:         Context ctx=null;
 6:         try {
 7:             ctx = new InitialContext();
 8:             listContext (ctx,"");
 9:         }
10:         catch (NamingException ex) {
11:             System.err.println (ex);
12:             System.exit(1);
13:         }
14:     }
15:
16:     private static void listContext (Context ctx, String indent) {
17:         try {
18:             NamingEnumeration list = ctx.listBindings("");
19:             while (list.hasMore()) {
20:                 Binding item = (Binding)list.next();
21:                 String className = item.getClassName();
22:                 String name = item.getName();
23:                 System.out.println(indent+className+" "+name);
24:                 Object o = item.getObject();
25:                 if (o instanceof javax.naming.Context)
26:                     listContext ((Context)o,indent+"  ");
27:             }
28:         }
29:         catch (NamingException ex) {
30:             System.err.println ("List error: "+ex);
31:         }
32:     }
33: }
						

Creating and Destroying Contexts

Binding a composite name will automatically create any intermediate sub-contexts required to bind the name. Binding the name com/sams/publishing/book/j2ee in 21 days creates the following sub-contexts if they don't already exist:

com
com/sams
com/sams/publishing
com/sams/publishing/book

You can explicitly create contexts with the Context.createSubcontext() method. The single method parameter is the name of the context. If this is a composite name, all intermediate contexts must already exist. The createSubContext() method will throw a NameAlreadyBoundException if the name already exists.

Note

Contrary to the API documentation, the J2EE RI naming service will automatically create any intermediate contexts.


Listing 3.7 shows a simple program for creating arbitrary contexts.

Listing 3.7. Full Text of JNDICreate.java
 1: import javax.naming.*;
 2: public class JNDICreate
 3: {
 4:     public static void main(String[] args) {
 5:         try {
 6:             if (args.length != 1) {
 7:                 System.out.println ("Usage: JNDICreate context");
 8:                 System.exit(1);
 9:             }
10:             Context ic = new InitialContext();
11:             ic.createSubcontext(args[0]);
12:         }
13:         catch (NamingException ex) {
14:              System.err.println(ex);
15:              System.exit(1);
16:         }
17:     }
18: }
						

The Context.destroySubcontext() method can destroy contexts. Again, the single method parameter is the name of the context. The context does not have to be empty, because the method will remove from the namespace any bound names and sub-contexts with the destroyed context.

Listing 3.8 shows a simple program for deleting arbitrary contexts.

Use this program with caution, because destroying the wrong context will render your J2EE server unusable. If you are using the J2EE RI, restarting the J2EE server can rectify a mistake; this might not be the case with other servers.

Listing 3.8. Full Text of JNDIDestroy.java
 1: import javax.naming.*;
 2: public class JNDIDestroy
 3: {
 4:     public static void main(String[] args) {
 5:         try {
 6:             if (args.length != 1) {
 7:                 System.out.println ("Usage: JNDIDestroy context");
 8:                 System.exit(1);
 9:             }
10:             Context ic = new InitialContext();
11:             ic.destroySubcontext(args[0]);
12:         }
13:         catch (NamingException ex) {
14:              System.err.println(ex);
15:              System.exit(1);
16:         }
17:     }
18: }
						

The destroyContext() method can throw a NameNotFoundException if the name doesn't exist and a NotContextException if the bound name is not a context.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.69.163