0 Replies Latest reply: May 9, 2009 10:12 AM by 843807 RSS

    Help - JavaBeans - Event Listening - EventListenerProxy

    843807
      Hi all, I have a question about how do you handle EventListenerProxy objects when creating a support for an event?

      I have been implementing an event listener support class (something additional to property/vetoable change events specific for my project) and it seemed to be very simple until I found the java.util.EventListenerProxy which caused several serious problems to me. The source (without doc. comments) of the mentioned class is here:
      public abstract class EventListenerProxy implements EventListener {
          private final EventListener listener;
      
          public EventListenerProxy(EventListener listener) {
              this.listener = listener;
          }
      
          public EventListener getListener() {
              return listener;
          }
      }
      By looking at it you can see that it is a valid EventListener, it means that it is an EventListener, and it contains a proxy object, which is also an EventListener and it can be another EventListenerProxy. So adding such a listener requires traversing its chain structure to get all child listener objects contained by it. And here are the problems:

      - The class is not parametrized so you are forced to check for the correct type of the proxy obtained from the getListener() method.

      - Although the listener attribute is private the getListener() method can be overridden (this is totally wrong and stupid as far as I can see!) so you are possible to create a chain of event listener proxy objects where the last event listener proxy object will point to the first. So traversing such a chain will result in an infinite loop. (Unless you use some additional checking for example with IdentityHashMap).

      Consider this example:
      public static class MyEventListenerProxy extends EventListenerProxy implements MyEventListener {
              private EventListener l;
              public MyEventListenerProxy() {
                  super(null); // sets null and completely ignores the private field of the EventListenerProxy class
              }
              public void setListener(EventListener l) {
                  this.l = l;
              }
              public EventListener getListener() {
                  return this.l;
              }
              public void myAction(MyEvent e) {
                  // handles event
              }
          }
      or simplier:
      public static class MyEventListenerProxy extends EventListenerProxy implements MyEventListener {
              public MyEventListenerProxy() {
                  super(null);
              }
              public EventListener getListener() {
                  return this;
              }
              public void myAction(MyEvent e) {
                  // handles event
              }
          }
      Then the following is possible:
      final List<MyEventListener> listProxyLooping = new ArrayList<MyEventListener>();
              for (int i = 0; i < 10; i ++) {
                  MyEventListenerProxy p = new MyEventListenerProxy();
                  if (i != 0)    p.setListener(listProxyLooping.get(i - 1));
                  listProxyLooping.add(p);
              }
      
              // makes the chain of listener proxy objects to be looping forever and reverses the list
              ((MyEventListenerProxy)listProxyLooping.get(0)).setListener(listProxyLooping.get(9));
              Collections.reverse(listProxyLooping);
      
              // guess what happens :)
              MyObject.addMyEventListener(listProxyLooping.get(0));
      - And the last thing is that why the constructor of this class does not check if the given listener is null. This forces me to do additional null checking when getting the proxy object.

      Personally I think that this class is another mistake of the Java Platform, such as the mutable Date class is, and it should be deprecated and its functionality should be replaced by something more secure and type-safer.

      So I am asking: Do you ignore EventListenerProxy objects? Or do you handle them, if yes please post how.