previous chapter table of contents next chapter

Listener List

Each listener for remote events must implement the RemoteEventListener interface:

 public interface RemoteEventListener                  extends java.rmi.Remote, java.util.EventListener {     public void notify(RemoteEvent theEvent)                 throws UnknownEventException,                        java.rmi.RemoteException; } 

Because it extends Remote , the listener will most likely be something like an RMI stub for a remote object, so that calling notify() will result in a call on the remote object, with the event being passed across to it.

In event generators, there are multiple implementations for handling lists of event listeners all the way through the Java core and extensions. There is no public API for dealing with event-listener lists, and so the programmer has to reinvent (or copy) code to pass events to listeners. There are basically two cases:

  • Only one listener can be in the list.
  • Any number of listeners can be in the list.

Single Listener

The case where there is only one listener allowed in the list can be implemented by using a single-valued variable, as shown in Figure 14-1.

click to expand
Figure 14-1: A single listener

This is the simplest case of event registration:

 protected RemoteEventListener listener = null; public EventRegistration addRemoteListener(RemoteEventListener listener)        throws java.util.TooManyListenersException { 
 if (this.listener == null {         this.listener = listener;     } else {         throw new java.util.TooManyListenersException();     }      return new EventRegistration(0L, this, null, 0L); } 

This is close to the ordinary Java event registration ”no really useful information is returned that wasn't known before. In particular, there is no lease object, so you could probably assume that the lease is being granted "forever," as would be the case with non-networked objects.

When an event occurs, the listener can be informed by the event generator calling fireNotify() :

 protected void fireNotify(long eventID,                           long seqNum) {     if (listener == null) {         return;     }     RemoteEvent remoteEvent = new RemoteEvent(this, eventID,                                               seqNum, null);     listener.notify(remoteEvent); } 

It is easy to add a handback to this: just add another field to the object, and set and return this object in the registration and notify methods . Far more complex is adding a non-null lease. Firstly, the event source has to decide on a lease policy, that is, for what periods of time it will grant leases. Then it has to implement a timeout mechanism to discard listeners when their leases expire. And finally, it has to handle lease renewal and cancellation requests , possibly using its lease policy again to make decisions. The landlord package would be of use here.

Multiple Listeners

For the case where there can be any number of listeners, the convenience class javax.swing.event.EventListenerList can be used. The object delegates some of the list handling to the convenience class, as shown in Figure 14-2.

click to expand
Figure 14-2: Multiple listeners

A version of event registration suitable for ordinary events is as follows :

 import javax.swing.event.EventListenerList; EventListenerList listenerList = new EventListenerList(); public EventRegistration addRemoteListener(RemoteEventListener l) {     listenerList.add(RemoteListener.class, l);     return new EventRegistration(0L, this, null, 0L); } public void removeRemoteListener(RemoteEventListener l) {     listenerList.remove(RemoteListener.class, l); } // Notify all listeners that have registered interest for // notification on this event type. The event instance // is lazily created using the parameters passed into // the fire method. protected void fireNotify(long eventID,                           long seqNum) {     RemoteEvent remoteEvent = null;     // Guaranteed to return a non-null array     Object[] listeners = listenerList.getListenerList();     // Process the listeners last to first, notifying     // those that are interested in this event     for (int n = listeners.length - 2; n >= 0; n -= 2) {         if (listeners[n] == RemoteEventListener.class) {             RemoteEventListener listener =                              (RemoteEventListener) listeners[n+1];             if (remoteEvent == null) {                 remoteEvent = new RemoteEvent(this, eventID,                                               seqNum, null);             }             try {                 listener.notify(remoteEvent);             } catch(UnknownEventException e) {                 e.printStackTrace();             } catch(java.rmi.RemoteException e) {                 e.printStackTrace();             }         }     } } 

In this case, a source object need only call fireNotify() to send the event to all listeners. (You may decide that it is easier to simply use a Vector of listeners.)

It is again straightforward to add handbacks to this. The only tricky point is that each listener can have its own handback, so they will need to be stored in some kind of map (say a HashMap ) keyed on the listener. Then, before notify() is called for each listener, the handback will need to be retrieved for the listener and a new remote event created with that handback.


A Programmer[ap]s Guide to Jini Technology
A Programmer[ap]s Guide to Jini Technology
ISBN: 1893115801
Year: 2000
Pages: 189

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net