JDK-4380536 : I want a method to remove all listeners from a Component
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic
  • Submitted: 2000-10-18
  • Updated: 2006-08-23
  • Resolved: 2006-08-23
Description
Name: rmT116609			Date: 10/18/2000


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)


Event Listeners can be a big pain to deal with once you are done with them. If
you have a Component (a Choice control, JList, JButton, etc.) and you are done
with it you need to remove all of the listeners that have been added to that
component.  This is not an impossible task, but it is made more difficult
because you need to keep track of all of the listeners that you have added.
It would be nice that have a few more methods at our disposal.  In addition to
Component's  getListeners(Class c) method it would be useful to have a
EventListener []listeners getAllListeners() which would return all of the
listeners.  Even more useful would be
    removeAllListeners() which would remove all of the listeners that have been
added.

I have a framework which launches various "applications" (java classes).  The
framework is also responsible for destroying the "applications".  The framework
should be like an Operating System and clean up after all "applications" no
matter how badly they behave.  The framework can not trust the "applications" to
clean up after themselves correctly.
(Review ID: 110989) 
======================================================================

Comments
EVALUATION We could believe that developers should take all the responsibility what they are doing when calling removeAllListeners() and this unlikely break existing applications but looking on this age and a low interest on this and an argument with 3rd party components(https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?messageID=14980&forumID=1463) I'm closing this RFE with "will not fix" conclusion.
23-08-2006

EVALUATION The suggested contribution seem has an important issue. This method is only insufficient for user listeners but it doesn't consider system listeners (preferably Swing). So once invoked that removeAllListeners() would probably break Swing event machinery. Suppose this change may not be accompished only from AWT side. To make suggested API avalable for developers we have to implement alternative mechanism dealing with listenets in Swing. Quick solutions are: 1. add boolean field to the Listener to reflect if it a system listener or is added by a developer. So when we are about to removeAllListeners() we should only process developer's instances. 2. force Swing to use their private API to operate with adding/removing listeners. Second approach looks much more complex.
18-08-2006

WORK AROUND Name: rmT116609 Date: 10/18/2000 static private void removeListeners(Component comp) { Method []methods = comp.getClass().getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; String name = method.getName(); if (name.startsWith("remove") && name.endsWith("Listener")) { Class []params = method.getParameterTypes(); if (params.length == 1) { EventListener []listeners = null; try { listeners = comp.getListeners(params[0]); }catch(Exception e){ // It is possible that someone could create a listener // that doesn't extend from EventListener. If so, ignore it System.out.println("Listener " + params[0] + " does not extend EventListener"); continue; } for ( int j = 0; j < listeners.length; j++) { try { method.invoke(comp, new Object[]{listeners[j]}); //System.out.println("removed Listener " + name + " for comp " + comp + "\n"); }catch(Exception e){ System.out.println("Cannot invoke removeListener method " + e); // Continue on. The reason for removing all listeners is to // make sure that we don't have a listener holding on to something // which will keep it from being garbage collected. We want to // continue freeing listeners to make sure we can free as much // memory has possible } } }else{ // The only Listener method that I know of that has more than // one argument is removePropertyChangeListener. If it is // something other than that, flag it and move on. if (!name.equals("removePropertyChangeListener")) System.out.println(" Wrong number of Args " + name); } } } } ======================================================================
14-09-2004

EVALUATION Though it can be done, a method to deal with all of a Component's listeners would be much easier. In the meantime, the following from ###@###.### might be helpful: Even with the new API [EventSetDescriptor.getGetListenerMethod()], the workaround is probably the best way to remove all the listeners. You could use Introspector.getBeanInfo() and get the EventSetDescriptors that would have a reference to the remove listener method. This would be a better way to do it so that subclasses of component will not have to override "removeAllListener()" to remove their specific listener types. Arguably, there are a finite number of listener types that get registered on a Component but using a reflective approach is much more future proof and will hedge against component subclasses that add listeners types to the EventListenerList. All bets are off if a component manages it's own listener lists. In that case the BeanInfo approach is best if the listeners are registered with the add/remove/get pattern. The problem with the BeanInfo approach is that it may fail to remove all the listeners for custom BeanInfos. ###@###.### 2003-04-28
28-04-2003