April 16, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Locating Resources Using JNDI (Java Naming and Directory Interface), Page 5

  • June 2, 2003
  • By Sams Publishing
  • Send Email »
  • More Articles »

Binding JNDI Objects

After you have obtained an initial context, you can use it to bind new objects into the naming service and look up objects that are bound to a name.

In J2EE applications, when working with EJBs, for example, the main use of JNDI is to look up objects that have already been bound. The J2EE server usually performs the actual binding of objects.

To bind an object to a name within a J2EE naming service, you use code similar to that shown in Listing 13.1. The code simply binds a java.lang.String object (Some_String) to the name sams/book.

Listing 13.1 Binding an Object to a Name (BindObject.java)

package com.conygre.jspdevhandbook.chapter13;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class BindObject
{
 public static final String TITLE = "sams/book";
 
 public static void main (String[] args) 
 {
   Object object = "Some_String";

   try 
   {
    Context initialContext = new InitialContext();

    initialContext.bind(TITLE, object);
    System.out.println("Bound object to name: " + TITLE);
   }
   catch (NamingException e) 
   {
    System.err.println("An error occurred while binding the object ("
             + object + ") to the name '" + TITLE + "'");
    e.printStackTrace();
   }   
 }
}

A couple of common errors can occur when you attempt to bind an object to a name. First, you must make sure that the object implements the Serializable interface so that the server can store a copy of the object.

Second, the Context.bind() method fails if an object is already bound to the name that you specify. In this case, a subclass of NamingException is thrown: NameAlreadyBoundException.

Note that the code in Listing 13.1 does not set values for any of the properties mentioned earlier in this chapter for specifying the service provider. This is because this example uses the J2EE RI, and the j2ee.jar file contains a jndi.properties file that is identical to the one mentioned earlier.

Name Persistence

You might have noticed that if you run the program from Listing 13.1 twice in succession, you get an error of the form:

An error occurred while binding the object (Some_String)
to the name 'sams/book'

javax.naming.NameAlreadyBoundException: Use rebind to override

However, if you restart the J2EE RI, then you do not get an error. This is due to the fact that the default naming service for the J2EE RI is a transient service. This means that any objects that are bound through configuration files in the SDK home directory are rebound when the server starts up, but any objects bound programmatically through the Context.bind() method are not.

Rebinding Objects

You have two options if you want to avoid the javax.naming.NameAlreadyBoundException mentioned earlier. The first is to unbind an existing object, and then bind the new one. The next section, "Unbinding Objects," describes this process.

The second option is to do what the NameAlreadyBoundExcpetion recommends: You can use the Context.rebind() method that unbinds the old object and binds the new one for you. In this case, the code from Listing 13.1 would use this method call rather than a call to bind():

initialContext.rebind(TITLE, object);
Unbinding Objects

The Context.unbind() method removes an object from a namespace. Generally this method is used when an application is closing down and you want to remove the object from the naming service so that other applications do not attempt to make use of the bound object. This is necessary because bindings are not automatically removed when an application that uses a naming service is shut down.

Another time that you commonly use the unbind() method is when you want to bind an object into a naming service under a name, but you first want to see if there is already an object bound under the name you are going to use. The advantage of using a combination of unbind()/bind() over just a call to rebind() is that you can add logic to see whether you should perform the bind() operation. For example, you might only want to bind the new object if it is of the same type (or a subclass) of the existing bound type:

String JNDI_NAME = "sams/book";
try
{
  Object o = initialContext.lookup(JNDI_NAME);
  if (o instanceof String)
    initialContext.unbind(JNDI_NAME);
}
catch (NameNotFoundException e)
{
  // ignore: means that the lookup failed, so there is no existing object
}

initialContext.bind(JNDI_NAME, "some other string");

There are three things that could happen with this code fragment when the lookup() method is invoked:

  • The lookup fails because there is no object bound to the name sams/book, in which case the NameNotFoundException is ignored and the new object is bound in under the name sams/book.

  • The lookup returns an object that is not of type java.lang.String, so the unbind() operation is not performed. In this case, the bind() method would throw a javax.naming.NameAlreadyBoundException.

  • The lookup returns an object that is of type java.lang.String, and so the existing object is unbound and the new string is bound in its place.

Renaming Objects

It is a simple matter to change the name under which an object is already bound into the naming service. You simply use the Context.rename() method, which takes the old and new names as parameters:

initialContext.rename("the_old_name", "the_new_name"); 

There are only two things to be aware of; the first is that the new name must be in the same context as the old name. The second is that the old name must be bound to an object, and the new name must not. A javax.naming.NamingException is thrown if these conditions are not met.

JNDI Name Lookup

By far the most common use of JNDI in Web applications is to look up objects that have been bound to names. To perform the lookup, you need two pieces of information:

  • The JNDI name that the object is bound to

  • The class of the bound object

After you know this information, all you need to do is use the Context.lookup() method to return a reference to the object, and then cast the reference to the correct type. The code in Listing 13.2 shows how to retrieve a bound object from a naming service. If you are running the code samples as you work through this chapter, make sure that you run the code in Listing 13.1 first. Then again, you might prefer not to so that you can see the code in the catch block executed.

Listing 13.2 Code That Looks Up a Bound Object (LookupObject.java)

package com.conygre.jspdevhandbook.chapter13;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class LookupObject
{
 public static void main (String[] args) 
 {
   try 
   {
    Context initialContext = new InitialContext();
    Object object = initialContext.lookup(BindObject.TITLE);

    if ( object instanceof java.lang.String) 
    {
     String s = (String) object;
     System.out.println("Looked up this object: " + s);
    }
    else 
    {
     System.err.println("Error: The looked up object is not of type "
              + "java.lang.String");
    }
   }
   catch (NamingException e) 
   {
    System.err.println("Couldn't find an object bound to the name "
             + BindObject.TITLE);
   }   
 } 
}

The if statement is simply a sanity check because the code from Listing 13.1 binds a java.lang.String object under the name sams/book. The code in the else statement is executed if the object returned from the lookup() method is not a String.





Page 5 of 7



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel