Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Mastering Enterprise JavaBeans™ and the Java 2 Platform, Enterprise Edition - Roman E

..pdf
Скачиваний:
41
Добавлен:
24.05.2014
Размер:
6.28 Mб
Скачать

574 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

Classes Context

Java Context

Packages Context

WinNT Context

 

CertSrv Context

ASP Context

 

 

System32 Context

 

 

 

InetServ Context

 

This branch shown of a hard

 

 

disk is an example of a naming

 

 

system, because it's a

 

IISAdmin Context

connected set of contexts.

 

 

 

Within this naming system, the namespace is every name shown above.

Figure B.6 Naming systems and namespaces.

the bindings of each naming system. Composite namespaces are illustrated in Figure B.7.

Initial Context Factories

One question commonly asked is, if you are to traverse a composite namespace, how do you know which naming system to look into first? For example, which namespace do you first look in when traversing the string http://www.trilogy

.com/products/products.asp?

The starting point of exploring a namespace is called an initial context. An initial context simply is the first context you happen to use. An initial context is a starting point for performing all naming and directory operations.

To acquire an initial context, you use an initial context factory. An initial context factory is responsible for churning out initial contexts. Initial context factories are provided by specific JNDI service providers. For example, there is an

Go back to the first page for a quick link to buy this book online!

Understanding the Java Naming And Directory Interface (JNDI) 575

DNS

NDS

LDAP

Printer Service

File System

Printers

User Information

Files

Figure B.7 A composite (federated) namespace.

LDAP initial context factory, as well as a File System initial context factory. These initial context factories know the specific semantics of a particular directory structure. They know how to acquire an arbitrary context that you can use as an initial starting context for traversing a directory structure.

Initial context factories are used for bootstrapping, or jump starting, your naming and directory service operations. This is quite similar to Java RMI. In RMI, you use the RMI naming facility to locate an RMI registry, which serves as a bootstrapping mechanism for identifying an initial remote object (see Appendix A). In JNDI, you use an initial context factory as a bootstrapping mechanism for identifying an initial naming system.

When you acquire an initial context, you must supply the necessary information for JNDI to acquire that initial context. For example, you could pass the IP

Go back to the first page for a quick link to buy this book online!

576 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

address of the LDAP directory you want to use, the port number that the LDAP directory accepts, the starting location within the LDAP tree, and the username/ password necessary to use the LDAP server.

Initial contexts are illustrated in Figure B.8.

Initial Context

JNDI client code

DNS

NDS

LDAP

Printer Service

File System

Printers

User Information

Files

Figure B.8 A composite (federated) namespace with an initial context.

Go back to the first page for a quick link to buy this book online!

Understanding the Java Naming And Directory Interface (JNDI) 577

Directory Concepts

Let’s now briefly touch on directory concepts. From our naming concepts, we learned that a context is an object that contains one or more bindings. An example of a context is a folder. A folder can contain names bound to files and other subfolders.

A directory context (or directory object) is a particular type of context that has attributes associated with it. Directory contexts are just like regular contexts. Both contexts and directory contexts can contain name-object bindings, just as a file folder contains files and subfolders. The value-add of directory contexts is that they can store other attributes as well. Going with our file system analogy, a directory attribute is similar to permissions on a folder. Permissions can be, for example, read-only permission to a folder or read-write permissions. These are natural attributes that go along with the folder. If you think of a context as a folder, think of a directory context as a folder with permissions. For example, you could use a directory context’s attributes to store usernames and passwords of users in your business.

Programming with JNDI

Now that you’ve seen the concepts behind JNDI, let’s put our theory into concrete use. This section will explain the details of the JNDI API, and it will show several examples of JNDI in action.

Setting Up the Required Software

To try out the examples in this appendix, you need the following software installed:

■■The Java Development Kit version 1.1.2 or higher.

■■The JNDI Java extension package. Alternatively, you can use another implementation of JNDI, such as BEA’s WebLogic.

■■Service providers for the particular directory you are using. We’ll be using the LDAP, File System, and RMI Registry providers in this appendix, so you’ll need to download them from the Sun Microsystems Web site.

■■If you’d like to try out the LDAP service provider, you’ll need to download an LDAP-compatible directory server. The University of Michigan provides a free one. America Online also provides an LDAP directory server (previously named the Netscape Directory Server), which is much easier to use than the University of Michigan’s. Be forewarned that configuring an LDAP server is not trivial. If you’re in a hurry, you may want to bypass this step.

Go back to the first page for a quick link to buy this book online!

578 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

For links to these products and more, see the book’s accompanying Web site. For tips and tricks in setting up LDAP servers, see the free JNDI tutorial on Sun Microsystems’ Web site.

The JNDI Packages

There are three core packages in JNDI:

The naming package, javax.naming, is used for accessing a naming service. As we first mentioned in this appendix, naming services associate names with objects and provide facilities for finding objects based on their names. We will cover the javax.naming package extensively.

The directory package, javax.naming.directory, is used for accessing naming services as well as directory services. The directory package extends the naming package. You can perform all naming service operations with the directory package. The directory package adds the ability to manipulate attributes associated with objects. While this is an important subject, we do not cover javax.naming.directory here because Enterprise JavaBeans does not depend on it.

The service provider interface (SPI), javax.naming.spi, is an interface to which service providers can plug in. We don’t cover the SPI in this book because it is intended for naming and directory service vendors.

Basic JNDI Steps

The following steps are necessary whenever you perform any JNDI operations:

1.Identify what service provider you are using. If you’re connecting to an LDAP service provider, you need to specify the LDAP Initial Context Factory.

2.Specify any ancillary information that the service provider may need. This is usually information the service provider needs to start up. Examples are the location of an LDAP directory on a network, usernames and passwords (for the LDAP service provider), or the location of a starting folder on your hard drive (for the File System service provider).

3.Acquire an initial context. To refresh your memory, a naming context is like a folder on a file system. Contexts store name-object bindings. For example, if you have a Windows NT machine, your c:\winnt folder can be thought of as a context. The c:\winnt folder contains a collection of names bound to objects, such as the name jview.exe that is bound to a file on a hard disk. The c:\winnt context might also contain the name system32 that is bound to a subfolder, or in JNDI terms, a subcontext. Thus, your initial context could be c:\winnt, or it might also be c:\winnt\system32.

Go back to the first page for a quick link to buy this book online!

Understanding the Java Naming And Directory Interface (JNDI) 579

But your initial context could not be c:\winnt\jview.exe because jview.exe is not a context. The initial context can also be a directory context. Directory contexts are naming contexts that can also store attributes, just as a folder can have permissions.

The following code snippet illustrates setting your environment properties and acquiring an initial context. The code is listed in Source B.1.

The code first chooses an initial context factory. The initial context factory will bootstrap us and acquire an initial context for us to begin navigating a directory structure. Remember, initial context factories are necessary so that JNDI knows what kind of directory structure we’re first using, such as an LDAP directory. In this example, we’ll use the File System service provider, which is very

package com.wiley.compBooks.roman.jndi.initctx;

import java.util.Properties;

/**

* Illustrates how to acquire a JNDI initial context */

public class InitCtx {

public static void main(String args[]) {

try {

Properties env = new Properties();

env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");

env.put(javax.naming.Context.PROVIDER_URL, "file:c:\\");

javax.naming.Context ctx =

new javax.naming.InitialContext(env);

System.out.println("Success!");

}

catch (javax.naming.NamingException e) { e.printStackTrace();

}

}

}

Source B.1 InitCtx.java.

Go back to the first page for a quick link to buy this book online!

580 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

easy to use because you don’t need to install and configure a complex directory product.

Following the initial context factory, we then identify the starting point on the file system that we want to begin navigating: specifically, the c:\ folder. This starting point is structured in the form of a Uniform Resource Locator (URL), and in JNDI it is called the provider URL because it’s a URL that the service provider accepts for bootstrapping.

Finally, we acquire an initial context to that folder. Normally at this point, you can begin to execute JNDI operations, such as binding data to directory trees, searching a directory tree, and so on. Our program simply terminates. Thus, you now know the basic first three steps for all JNDI programs.

Ideally, you should not couple the JNDI initialization settings with your Java code. A much better design model is to pass properties to your Java program. That way, you can change the location, type, and parameters of your JNDI provider in a declarative rather than programmatic fashion. This saves you from recompiling your Java code and enables non-Java savvy users to customize your products without modifying source code. This source code may not even be available if you ship your products only as .class files.

Exploring the javax.naming Package

Now that you’ve got your feet wet by learning how to connect to JNDI, let’s take a more in-depth look at the various classes and interfaces of JNDI, so that we can move on to more interesting applications.

Tables B.1 and B.2 enumerate the more interesting interfaces and classes found in javax.naming. You’ll notice that many of the interface and class names correspond to the concepts we discussed earlier, such as a Name, a Binding, and a Context.

Table B.1 Selected Interfaces from the javax.naming Package

INTERFACE

DESCRI PTION

Context

A naming context that contains name-object bindings. Exposes

 

methods to bind, rebind, and unbind a name to an object. Also can

 

create/destroy subcontexts, list the names currently bound to

 

objects, look up an object based on a name, and more.

Name

Rather than working with raw Strings, JNDI abstracts the notion of

 

a Name, such as /etc/fstab or cn=Ed Roman, ou=People. A Name

 

can be atomic or compound, as defined by the class that

 

implements the name. Exposes methods to manipulate the name.

 

 

Go back to the first page for a quick link to buy this book online!

Understanding the Java Naming And Directory Interface (JNDI)

 

581

 

 

 

INTERFACE

DESCRI PTION

 

NameParser

A NameParser assists in constructing a particular Name object.

 

 

NameParsers know the specific syntax that an underlying directory

 

structure uses. For example, an LDAP NameParser knows how an

 

LDAP string is constructed, whereas a File System NameParser

 

 

knows how to format a File System string. As we mentioned earlier

 

in this chapter, naming conventions differ from directory to

 

 

directory. NameParsers insulate you from these differences.

 

NamingEnumeration

NamingEnumerations are used to enumerate the list of objects

 

 

returned by list and search operations exposed by Context objects.

Table B.2 Selected Classes from the javax.naming Package

CLASS

DESCRI PTION

NameClassPair

These classes are used to associate a name with an object. A

and Binding

NameClassPair associates a JNDI Name object with a Java class,

 

and it is a fairly weak kind of association because a NameClassPair

 

associates only a Name with a class.

 

A JNDI Binding extends NameClassPair. Bindings associate a Name

 

with a class as well as a specific object instance. This is the

 

“binding” concept we have been referring to in this chapter.

CompositeName

A composite name is a name that spans more than one

 

namespace, as when an LDAP namespace is combined with a file

 

system namespace. If your composite name is not encapsulated

 

within a CompositeName object, you can use a java.util.String

 

instead. To indicate different namespaces within a composite name

 

String, separate them with a “/” character.

CompoundName

A CompoundName is zero or more atomic names put together, such

 

as /etc/fstab. Each of the atomic names in a compound name must

 

be from the same namespace (for example, there can be no mixing

 

and matching of DNS with file system names). You can pass a special

 

java.util.Properties object to the CompoundName constructor to

 

help specify the syntax of the naming system you are using.

InitialContext

To perform any naming operations, you first need an InitialContext.

 

Because an initial context is a special kind of context, the InitialContext

 

class implements the Context interface. You pass the constructor of

 

InitialContext information about where the directory is, security

 

information, etc., so that it can bootstrap. Once you’ve got the ini-

 

tial context, you can start traversing the directory structure, perform

 

lookup operations, and bind objects. Initial contexts are generated

 

from Initial Context Factories (javax.spi.InitialContextFactory) such

 

as the LDAP Initial Context Factory.

 

continues

Go back to the first page for a quick link to buy this book online!

582

 

 

M A S T E R I N G E N T E R P R I S E J A V A B E A N S

Table B.2

Continued

 

 

CLASS

DESCRI PTION

LinkRef

A LinkRef is a link that can span possibly multiple namespaces. A

 

 

 

LinkRef is a symbolic link within a directory structure. By using

 

 

 

LinkRef, you can link one part of a directory to another, just as a

 

 

 

symbolic link in UNIX (or a shortcut, in Windows) is a link from one

 

 

 

part of a file system to another.

 

 

 

 

Example: An Interactive Browser

Now that you’ve taken a rough look at the javax.naming concepts and API, let’s put JNDI to use. This example will put some common naming operations together to create an interactive browser. Our browser will be able to peruse any kind of directory structure because it is entirely based on the unified JNDI client API. This example will illustrate a practical JNDI application using both the File System service provider and the LDAP service provider. Specifically, this utility will provide functionality to traverse a directory structure, add and remove folders (contexts), get a folder (context) listing, and view a file (the latter is possible with the File System service provider only). This interactive browser will use familiar UNIX commands to traverse a file system, including the following:

cd to change folders (contexts) ls to get a listing of subcontexts mv to rename a context

cat to view a file

You can use this utility to browse your own hard disk, for example, or to browse an LDAP directory.

The code is shown in Source B.2. Although it is fairly self-explanatory, we’ll take a look at some key pieces in detail.

Browser.java starts off by creating a class and initializing some variables:

ctx = new InitialContext(System.getProperties()); parser = ctx.getNameParser("");

currName = parser.parse("");

We create the Initial Context based on System properties passed in with the -D interpreter switch. This means that we aren’t specifying a particular service provider. The System properties need to define the Initial Context Factory to identify the service provider, the Provider URL, and any other parameters such as authentication information needed by the service provider.

Go back to the first page for a quick link to buy this book online!

Understanding the Java Naming And Directory Interface (JNDI) 583

package com.wiley.compBooks.roman.jndi.browser;

import javax.naming.*; import java.io.*; import java.util.*;

/**

* Interactive directory structure browser. */

public class Browser {

/**

* Main() is just a wrapper that starts the directory browsing. */

public static void main (String[] args) { try {

new Browser().browse();

}

catch (Exception e) { System.err.println(e); e.printStackTrace();

}

}

//Initial Context protected Context ctx;

//This JNDI Name object is used to track the current

//context (folder) we're in as we traverse the directory tree protected Name currName;

//We use a NameParser to generate Name objects for us.

//A NameParser knows how to construct a Name using

//a proprietary service provider syntax, such as

//"c:\winnt" for the File System service provider, or

//"cn=Ed Roman, ou=People, o=Airius.com" for the LDAP

//service provider.

protected NameParser parser;

/*

* Constructor called from main(). Initializes things. */

public Browser() throws Exception { /*

*1) Create the initial context. Parameters are

*supplied in the System properties.

*/

ctx = new InitialContext(System.getProperties());

Source B.2 Browser.java (continues).

Go back to the first page for a quick link to buy this book online!