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 handling events generated by the JNDI. Typically, an object implements a subinterface of NamingListener rather than directly implement 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

In addition to serving as the root interface, this interface specifies how a registered listener is to be notified of errors. The interface defines a single method: namingExceptionThrown()(in the API reference documentation). This method is invoked by the service provider when an error has occurred while it was collecting data for generating events that the listener is interested in. For example, the server might have gone off-line, 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 user of the application so 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 is for handling events that affect the namespace, this includes adding, removing, and renaming an object. An object that implements that 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 it 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 given in the Naming Event Section.

Handling Object Changes

ObjectChangeListener is for handling 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 have been removed or replaced.

An object that implements the ObjectChangeListener interface must provide definitions for objectChanged()(in the API reference documentation) method 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 an object being removed 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, you should define one listener that implements both interfaces. That way, the service provider might be able to optimize by collecting data about both types of changes with one request to the server. It also reduces the number of listeners the provider must manage and 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