Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
|
Relates :
|
Name: jk109818 Date: 01/22/2002 FULL PRODUCT VERSION : java version "1.4.0-beta3" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta3-b84) Java HotSpot(TM) Client VM (build 1.4.0-beta3-b84, mixed mode) Same problem occurs under 1.3.1_01. glibc-2.1.3-21 Linux jesse_laptop.netbeans.com 2.2.12-20 #1 Mon Sep 27 10:40:35 EDT 1999 i686 unknown Red Hat Linux release 6.1 (Cartman) A DESCRIPTION OF THE PROBLEM : Various Swing action containers, for example AbstractButton, JMenu, and JPopupMenu, permit a javax.swing.Action to be added directly as of 1.3. They listen for property changes on property "enabled" in order to update action state. However if the Action implementation fires a PropertyChangeEvent with a null newValue, these containers simply throw NPE. The reason is obvious in their code, e.g. JPopupMenu.java: } else if (propertyName.equals("enabled")) { Boolean enabledState = (Boolean) e.getNewValue(); menuItem.setEnabled(enabledState.booleanValue()); The code should check for enabledState == null and if so, use ((Action)e.getSource()).isEnabled() instead. It should also trigger the clause if propertyName == null. I imagine there are other such places in the code, I have only noticed these. According to the JavaBeans Specification it is acceptable to use a null newValue (or oldValue, or propertyName) in case an event source finds it too expensive to compute old and new values, or is not sure whether the values will actually be needed by someone but wishes to ensure that a change is fired nonetheless: http://java.sun.com/j2se/1.3/docs/api/java/beans/PropertyChangeEvent.html "Null values may be provided for the old and the new values if their true values are not known. An event source may send a null object as the name to indicate that an arbitrary set of if its properties have changed. In this case the old and new values should also be null." I could see no documentation overriding this proviso specifically for Action's, so it seems that the containers are at fault. FYI, bugs and troubles in NetBeans/Forte for Java caused by this: http://www.netbeans.org/issues/show_bug.cgi?id=13084 http://openide.netbeans.org/servlets/ReadMsg?msgId=219999&listName=dev STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Compile and run the enclosed class. When the frame appears, select the menu item; an NPE is thrown. Select the toolbar button; ditto. Select the button and when the popup menu appears, select its item; ditto. EXPECTED VERSUS ACTUAL BEHAVIOR : Expected results: all three uses of the action do nothing and throw no exception. Actual results: they do nothing but throw exceptions, see Error Messages section. ERROR MESSAGES/STACK TRACES THAT OCCUR : java.lang.NullPointerException at javax.swing.JMenu$ActionChangedListener.propertyChange(JMenu.java:678) at javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:267) at javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:235) at javax.swing.AbstractAction.firePropertyChange(AbstractAction.java:181) at TestNullPropChangeNewValuesFromAction.actionPerformed(TestNullPropChangeNewValuesFromAction.java:10) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1770) at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1823) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:422) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:260) at javax.swing.AbstractButton.doClick(AbstractButton.java:292) at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:1094) at javax.swing.plaf.basic.BasicMenuItemUI$MenuDragMouseHandler.menuDragMouseReleased(BasicMenuItemUI.java:993) at javax.swing.JMenuItem.fireMenuDragMouseReleased(JMenuItem.java:585) at javax.swing.JMenuItem.processMenuDragMouseEvent(JMenuItem.java:482) at javax.swing.JMenuItem.processMouseEvent(JMenuItem.java:429) at javax.swing.MenuSelectionManager.processMouseEvent(MenuSelectionManager.java:282) at javax.swing.plaf.basic.BasicMenuUI$MouseInputHandler.mouseReleased(BasicMenuUI.java:337) at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:230) at java.awt.Component.processMouseEvent(Component.java:5020) at java.awt.Component.processEvent(Component.java:4819) at java.awt.Container.processEvent(Container.java:1383) at java.awt.Component.dispatchEventImpl(Component.java:3527) at java.awt.Container.dispatchEventImpl(Container.java:1440) at java.awt.Component.dispatchEvent(Component.java:3368) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3219) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:2930) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:2866) at java.awt.Container.dispatchEventImpl(Container.java:1426) at java.awt.Window.dispatchEventImpl(Window.java:1568) at java.awt.Component.dispatchEvent(Component.java:3368) at java.awt.EventQueue.dispatchEvent(EventQueue.java:448) at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:193) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:147) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:141) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:133) at java.awt.EventDispatchThread.run(EventDispatchThread.java:101) java.lang.NullPointerException at javax.swing.AbstractButton$ButtonActionPropertyChangeListener.propertyChange(AbstractButton.java:1154) at javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:267) at javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:235) at javax.swing.AbstractAction.firePropertyChange(AbstractAction.java:181) at TestNullPropChangeNewValuesFromAction.actionPerformed(TestNullPropChangeNewValuesFromAction.java:10) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1770) at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1823) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:422) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:260) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:261) at java.awt.Component.processMouseEvent(Component.java:5020) at java.awt.Component.processEvent(Component.java:4819) at java.awt.Container.processEvent(Container.java:1383) at java.awt.Component.dispatchEventImpl(Component.java:3527) at java.awt.Container.dispatchEventImpl(Container.java:1440) at java.awt.Component.dispatchEvent(Component.java:3368) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3219) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:2930) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:2866) at java.awt.Container.dispatchEventImpl(Container.java:1426) at java.awt.Window.dispatchEventImpl(Window.java:1568) at java.awt.Component.dispatchEvent(Component.java:3368) at java.awt.EventQueue.dispatchEvent(EventQueue.java:448) at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:193) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:147) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:141) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:133) at java.awt.EventDispatchThread.run(EventDispatchThread.java:101) java.lang.NullPointerException at javax.swing.JPopupMenu$ActionChangedListener.propertyChange(JPopupMenu.java:393) at javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:267) at javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:235) at javax.swing.AbstractAction.firePropertyChange(AbstractAction.java:181) at TestNullPropChangeNewValuesFromAction.actionPerformed(TestNullPropChangeNewValuesFromAction.java:10) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1770) at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1823) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:422) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:260) at javax.swing.AbstractButton.doClick(AbstractButton.java:292) at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:1094) at javax.swing.plaf.basic.BasicMenuItemUI$MouseInputHandler.mouseReleased(BasicMenuItemUI.java:934) at java.awt.Component.processMouseEvent(Component.java:5020) at java.awt.Component.processEvent(Component.java:4819) at java.awt.Container.processEvent(Container.java:1383) at java.awt.Component.dispatchEventImpl(Component.java:3527) at java.awt.Container.dispatchEventImpl(Container.java:1440) at java.awt.Component.dispatchEvent(Component.java:3368) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3219) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:2930) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:2866) at java.awt.Container.dispatchEventImpl(Container.java:1426) at java.awt.Window.dispatchEventImpl(Window.java:1568) at java.awt.Component.dispatchEvent(Component.java:3368) at java.awt.EventQueue.dispatchEvent(EventQueue.java:448) at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:193) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:147) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:141) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:133) at java.awt.EventDispatchThread.run(EventDispatchThread.java:101) This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.awt.FlowLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.*; public class TestNullPropChangeNewValuesFromAction extends AbstractAction { public TestNullPropChangeNewValuesFromAction() { super("Hi mom"); } public void actionPerformed(ActionEvent e) { firePropertyChange("enabled", null, null); } public static void main (String args[]) { JFrame frame = new JFrame("TestNullPropChangeNewValuesFromAction"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JMenuBar menubar = new JMenuBar(); JMenu menu = new JMenu("Test"); menu.add(new TestNullPropChangeNewValuesFromAction()); menubar.add(menu); frame.setJMenuBar(menubar); frame.getContentPane().setLayout(new FlowLayout()); JToolBar toolbar = new JToolBar(); toolbar.add(new TestNullPropChangeNewValuesFromAction()); frame.getContentPane().add(toolbar); final JButton button = new JButton("Show popup"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JPopupMenu popup = new JPopupMenu(); popup.add(new TestNullPropChangeNewValuesFromAction()); popup.show(button, 10, 10); } }); frame.getContentPane().add(button); frame.pack(); frame.setVisible(true); } } ---------- END SOURCE ---------- CUSTOMER WORKAROUND : A work around is to always be sure to pass a newValue (and a property name). The disadvantage is potential loss of efficiency, depending on the application. (Review ID: 137658) ======================================================================
|