malaikuangren

What is the purpose or drive to build thing like (xxx),How can it achieve the original goal of design?
Understanding JNDI

 

What Is JNDI?
JNDI comes with two interfaces: the Application Programming Interface (API) and the Service Provider Interface (SPI). You can use the API in an application to access a naming or directory service. You can use the SPI to program a new service to be used as a naming or directory service.
By providing a well-designed, object-oriented interface to access the naming and directory services, Java programmers need not be bogged down by the details and idiosyncrasies that are involved with accessing a native library of one of these services. Broad support exists for JNDI and there are at least 10 service providers who have provided implementations according to the SPI specification.

How JNDI Works (for LDAP, but is a common way for the others. like for jms)

To use JNDI, we need Sun's Java Development Kit or higher, JNDI Software Development kit , the JNDI LDAP Service Provider and an LDAP-compliant directory server such as Netscape's iPlanet Directory server.

Firstly we have to get a reference to an object that implements the DirContext interface. But mostly an InitialDirContext object has been used. This object takes a hash table as a parameter and this hash table can contain a number of different references and at the minimum, it should contain a reference to a field with the key Context.INITIAL_CONTEXT_FACTORY with a value of the fully qualified class name of the service provider, and a field with the key Context.PROVIDER_URL with a value containing the protocol, hostname and port number to the LDAP server like this: ldap://localhost:389, where 389 is the default LDAP port. Next create a Hashtable to store the environment variables that JNDI will to connect to the directory service. And we have to specify the fully qualified package name of our JNDI provider as specified in the API followed by specifying the hostname and port number to our LDAP server. Finally we get a reference to our initial directory context with a call to the InitialDirContext constructor, giving it our Hashtable as its only parameter. A directory context tells JNDI what service provider we will be using, what naming/directory server we will be connecting to, what location we will be accessing the directory from initially and any authentication information.

The most important operation we use on a LDAP server is searching. The search is being performed using the search() method of an object that implements the DirContext interface such as the InitialDirContext class. The minimum requirement for this is the search base and a filter. There are other parameters we can use to help manage the results. If the search is successful, a NamingEnumeration object will be returned. Once we get the initial context, we next specify the scope of our search, which is set in the SearchControls object, which is an optional parameter to the search() method of a DirContext object. After specifying the scope, we can perform the actual search. Each element in a NamingEnumeration object will contain a single SearchResult object, which we can retrieve as below:

SearchResult sr = (SearchResult) results.next();. We can get the DN of an entry by String dn = sr.getName(). To get the attributes of an entry we can use the getAttributes() method of the SearchResult class. This will return a concrete object that implements the Attributes interface like the InitialDirContext class returns a BasicAttributes object. Once we have an Attributes object, we can use a NamingEnumeration object, which contains methods to step through each attribute that was returned by the search process. There are many methods for returning the name of the attribute and values of the individual attribute. Retrieving a specific set of attributes from an individual entry is very quick and but general searching seems to be quite not practical.

JNDI also can be used to add new entries to the server, delete entries and modify existing entries. Actually adding entries to a LDAP server using JNDI is not that much easy. Actually the primary goal of JNDI is to read/write Java objects to the network. To store an entry in a LDAP server using JNDI, we have to bind an object to a Distinguished Name (DN). That is, each and every object we store in the server must have a DN associated with it. DN is actually the unique name that each entry in a LDAP server must possess. Every directory service is bound to have a unique name for each object just like no two files in the same directory in our file system is the same.

To store an entry in the LDAP server, we must create a class that implements the DirContext interface. This interface depicts how the object should be stored in and retrieved from the directory server and provides various sophisticated data handling techniques and is the most basic interface for building a directory service provider. The InitialDirContext interface will actually perform an LDAP add operation. Modifications to an entry can be accomplished with the ModificationItem and BasicAttribute classes. For deleting entries from the LDAP server, we have to call the destroySubContext() method of the DirContext interface.

example code looks like following:

for LDAP

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389");
DirContext ctx = new InitialDirContext(env);

more example code for JMS JNDI:

        Hashtable env;
        Context    ctx = null;
        env = new Hashtable();
        // Store the environment variables that tell JNDI which initial context
        // to use and where to find the provider.
        // For use with the File System JNDI Service Provider
        env.put(Context.INITIAL_CONTEXT_FACTORY, 
        "com.sun.jndi.fscontext.RefFSContextFactory");
        env.put(Context.PROVIDER_URL, url);
        try {
        // Create the initial context.
        ctx = new InitialContext(env);
        } catch (NamingException ne)  {
        System.err.println("Failed to create InitialContext.");
        System.err.println("The Context.PROVIDER_URL used/specified was: " + url);
        System.err.println("Please make sure that the path to the above URL exists");
        System.err.println("and matches with the objstore.attrs.java.naming.provider.url");
        System.err.println("property value specified in the imqobjmgr command files:");
        System.err.println("\tadd_cf.props");
        System.err.println("\tadd_q.props");
        System.err.println("\tdelete_cf.props");
        System.err.println("\tdelete_q.props");
        System.err.println("\tlist.props\n");
        System.err.println("\nThe exception details:");
        ne.printStackTrace();
        System.exit(-1);
        }
try {
            // Lookup my connection factory from the admin object store.
            // The name used here here must match the lookup name 
            // used when the admin object was stored.
        System.out.println("Looking up Connection Factory object with lookup name: "
            + MYCF_LOOKUP_NAME);
            cf = (javax.jms.ConnectionFactory) ctx.lookup(MYCF_LOOKUP_NAME);
        System.out.println("Connection Factory object found.");
        } catch (NamingException ne)  {
        System.err.println("Failed to lookup Connection Factory object.");
        System.err.println("Please make sure you have created the Connection Factory object using the command:");
        System.err.println("\timqobjmgr -i add_cf.props");

        System.err.println("\nThe exception details:");
        ne.printStackTrace();
        System.exit(-1);
        }

    try {
            // Lookup my queue from the admin object store.
            // The name I search for here must match the lookup name used when
            // the admin object was stored.
        System.out.println("Looking up Queue object with lookup name: "
            + MYQUEUE_LOOKUP_NAME);
            queue = (javax.jms.Queue)ctx.lookup(MYQUEUE_LOOKUP_NAME);
        System.out.println("Queue object found.");
        } catch (NamingException ne)  {
        System.err.println("Failed to lookup Queue object.");
        System.err.println("Please make sure you have created the Queue object using the command:");
        System.err.println("\timqobjmgr -i add_q.props");

        System.err.println("\nThe exception details:");
        ne.printStackTrace();
        System.exit(-1);
        }
try {
        System.out.println("Creating connection to broker.");
            connection = cf.createConnection();
        System.out.println("Connection to broker created.");
        } catch (JMSException e)  {
        System.err.println("Failed to create connection.");
        System.err.println("Please make sure that the broker was started.");

        System.err.println("\nThe exception details:");
        e.printStackTrace();
        System.exit(-1);
        }
try {
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

            // Create the MessageProducer and MessageConsumer 
            msgProducer = session.createProducer(queue); 
            msgConsumer = session.createConsumer(queue); 

            // Tell the provider to start sending messages.
            connection.start();

            msg = session.createTextMessage("Hello World");

            // Publish the message
            System.out.println("Publishing a message to Queue: " + queue.getQueueName());
            msgProducer.send(msg, DeliveryMode.NON_PERSISTENT, 4, 0);

            // Wait for it to be sent back.
            rcvMsg = (TextMessage) msgConsumer.receive();

            System.out.println("Received the following message: " + rcvMsg.getText());

            connection.close();

        } catch (JMSException e)  {
        System.err.println("JMS Exception: " + e);
        e.printStackTrace();
        System.exit(-1);
        }

JNDI Architecture

A variety of naming and directory services exist in production today. These include services such as:
• Lightweight Directory Access Protocol (LDAP)
• Domain Name Server (DNS)
• Network Information Service (NIS)
• Remote Method Invocation (RMI)
Using the JNDI SPI, the service providers for these industry naming and directory services provide a mapping from JNDI to their particular service. The Java applications can then use the JNDI API to access any individual service uniformly. Access to the service is provided via a Naming Manager.
A complete list of the existing service providers can be located at:
http://java.sun.com/products/jndi/serviceproviders.html

the JNDI Structure Picture:

posted on 2012-07-03 21:09  malaikuangren  阅读(243)  评论(0编辑  收藏  举报