Previous | Next | Trail Map | Beyond the Basics | Event Notification

Event Listeners

A listener in the JNDI is represented by the NamingListener(in the API reference documentation) interface. This is the root interface for objects that handles events generated by the JNDI. Typically, an object implements a subinterface of NamingListener rather than directly implementing NamingListener.

The javax.naming.event(in the API reference documentation) package contains two subinterfaces of NamingListener: ObjectChangeListener(in the API reference documentation) and NamespaceChangeListener(in the API reference documentation). The javax.naming.ldap(in the API reference documentation) package contains one subinterface: UnsolicitedNotificationListener(in the API reference documentation). This subinterface is discussed in the LDAP Unsolicited Notifications section.

Handling Errors

The NamingListener interface not only serves as the root interface but also specifies how a registered listener is to be notified of errors. It defines a single method: namingExceptionThrown()(in the API reference documentation). This method is invoked by the service provider when an error occurs while the provider is collecting data for generating events that the listener is seeking. For example, the server might have gone offline or cannot collect any more data in that part of the directory. When that occurs, the service provider deregisters the listener and invokes namingExceptionThrown() on the listener to notify it of the problem. This allows the listener to take action, such as notifying the application's user that the lack of events is due to a problem rather than the nonoccurrence of events.

See the Listener Registration section for details on how to handle errors when registering listeners.

Handling Namespace Changes

NamespaceChangeListener handles events that affect the namespace, including the addition, removal, and renaming of an object. An object that implements this interface must provide definitions for the three methods declared in the interface, as well as for namingExceptionThrown() (from the NamingListener interface).

Here is an example of a NamespaceChangeListener.

public class SampleNCListener implements NamespaceChangeListener {
    private String id;

    public SampleNCListener(String id) {
	this.id = id;
    }

    public void objectAdded(NamingEvent evt) {
	System.out.println(id + ">>> added: " + evt.getNewBinding());
    }
    public void objectRemoved(NamingEvent evt) {
	System.out.println(id + ">>> removed: " + evt.getOldBinding());
    }

    public void objectRenamed(NamingEvent evt) {
	System.out.println(id + ">>> renamed: " + evt.getNewBinding() + " from " +
	    evt.getOldBinding());
    }

    public void namingExceptionThrown(NamingExceptionEvent evt) {
	System.out.println(id + ">>> SampleNCListener got an exception");
	evt.getException().printStackTrace();
    }
}
When an object has been added, getOldBinding() will always return null because it wasn't in the namespace prior to its being added. When an object has been removed, getNewBinding() will always be null because it won't be in the namespace after it has been removed. More details about the old and new bindings are in the Naming Event section.

Handling Object Changes

ObjectChangeListener handles events that affect an object's contents, for example, if an object's binding has been replaced with another or one of an object's attributes has been removed or replaced.

An object that implements the ObjectChangeListener interface must provide definitions for objectChanged()(in the API reference documentation) as well as for namingExceptionThrown() (from the NamingListener interface).

Here is an example of an ObjectChangeListener.

public class SampleOCListener implements ObjectChangeListener {
    private String id;

    public SampleOCListener(String id) {
	this.id = id;
    }

    public void objectChanged(NamingEvent evt) {
	System.out.println(id + ">>> object changed: " + evt.getNewBinding() +
	    " from " + evt.getOldBinding());
    }

    public void namingExceptionThrown(NamingExceptionEvent evt) {
	System.out.println(id + ">>> SampleOCListener got an exception");
	evt.getException().printStackTrace();
    }
}
Even though this example displays both the old and new bindings for an object that has changed, some or all of that information might not be available if it is not supplied by the service provider or naming/directory server. More details about the old and new bindings are given in the Naming Event section.

Note that removing an object is a namespace change not an object content change. An application interested in both should use a listener that implements both NamespaceChangeListener and ObjectChangeListener, as described next.

Handling More Than One Type of Changes

If you are interested in both namespace changes and object content changes, then you should define one listener that implements both interfaces. In that way, the service provider might be able to optimize the resources used for the registration by collecting data about both types of change with one request to the server. It can also reduce the number of listeners the provider must manage as well as your application's code size.

Here is an example of a listener that implements both NamespaceChangeListener and ObjectChangeListener.

public class SampleListener 
implements NamespaceChangeListener, ObjectChangeListener {
    private String id;

    public SampleListener(String id) {
	this.id = id;
    }

    public void objectAdded(NamingEvent evt) {
	System.out.println(id + ">>> added: " + evt.getNewBinding());
    }
    public void objectRemoved(NamingEvent evt) {
	System.out.println(id + ">>> removed: " + evt.getOldBinding());
    }

    public void objectRenamed(NamingEvent evt) {
	System.out.println(id + ">>> renamed: " + evt.getNewBinding() + " from " +
	    evt.getOldBinding());
    }

    public void objectChanged(NamingEvent evt) {
	System.out.println(id + ">>> object changed: " + evt.getNewBinding() +
	    " from " + evt.getOldBinding());
    }

    public void namingExceptionThrown(NamingExceptionEvent evt) {
	System.out.println(id + ">>> SampleNCListener got an exception");
	evt.getException().printStackTrace();
    }
}


Previous | Next | Trail Map | Beyond the Basics | Event Notification