JDK-6442683 : JMenuItem$MenuItemPropertyChangeListener doesnt have default constuctor
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 5.0
  • Priority: P5
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2006-06-23
  • Updated: 2011-02-16
  • Resolved: 2006-07-12
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
The javax.swing.JMenuItem$MenuItemPropertyChangeListener class does not have a default no Argument constructor, which is required for serialization, even though the class implements the Serializable interface. When an object of JMenu is de-serialized then an exception of type ���javax.swing.JMenuItem$MenuItemPropertyChangeListener; no valid constructorjava.io.InvalidClassException: javax.swing.JMenuItem$MenuItemPropertyChangeListener; no valid constructor��� is thrown.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Serialize a new JMenu object to file ensuring the JMenu object is constructed with an AbstractAction derived object as the argument to the constructor. Then de-serialize the object from file and then an exception is thrown.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No exception should be thrown and the object should have been deserialized from file
ACTUAL -

An exception is thrown and the object isn���t deserialized from file.



ERROR MESSAGES/STACK TRACES THAT OCCUR :
���javax.swing.JMenuItem$MenuItemPropertyChangeListener; no valid constructorjava.io.InvalidClassException: javax.swing.JMenuItem$MenuItemPropertyChangeListener; no valid constructor���

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class JTestApplet extends JApplet
{

	private javax.swing.JPanel jContentPane = null;

	/**
	 * @throws java.awt.HeadlessException
	 */
	public JTestApplet() throws HeadlessException
	{
		super();
	
		init();
	}

	public static void main(String[] args) {
	}
	/**
	 * This method initializes this
	 *
	 * @return void
	 */
	public void init() {
		this.setSize(300, 200);
		this.setContentPane(getJContentPane());
	}
	/**
	 * This method initializes jContentPane
	 *
	 * @return javax.swing.JPanel
	 */
	private javax.swing.JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new javax.swing.JPanel();
			jContentPane.setLayout(new BorderLayout());
		}
		return jContentPane;
	}





	/* (non-Javadoc)
	 * @see java.applet.Applet#start()
	 */
	public void start()
	{
		File serFile = null;
		try
		{
			String strTempDir = System.getProperty("java.io.tmpdir");
				
			serFile = new File(strTempDir + "\\00000001.ser");
	
			////////////////////////////////////////////
			FileOutputStream outStrm = new FileOutputStream(serFile);

			ObjectOutputStream outstr = new ObjectOutputStream(outStrm);
			
			
		//////////////////////////////////////////////////////////
			
			//create the JMenuItem derived JMenu to serialize with an action for the constructor
			
			JMenu menu = new JMenu(new MyAction("action"));
			
			//////////////////////////////////////////////////////////////
			
			outstr.writeObject(menu); //serialize the menu
				
			outstr.flush();
			outStrm.close();
			outstr.close();
	
			serFile = null;
						
		}
		catch(Throwable e)
		{
			System.out.println("Serialization " + e.getMessage() + e);
		}
			
	}

	/* (non-Javadoc)
	 * @see java.applet.Applet#stop()
	 */
	public void stop()
	{
		try
		{
		//////////////////////////////////////////////////////////////
	
			String strTempDir = System.getProperty("java.io.tmpdir");
				
			File serFile = new File(strTempDir + "\\00000001.ser");
	
			
			if(serFile.exists() == false)
				return;
		
			//////////////////////////////////////////////////////////////
			////////file exists so we de-serialize it////////////////////////
				
			FileInputStream inStrm = new FileInputStream(serFile);
			ObjectInputStream in = new ObjectInputStream(inStrm);
			
			//now read back the JMenu Object
	
			JMenu menu = (JMenu)in.readObject();
			
			
				
			in.close();
			inStrm.close();
	
			serFile.delete(); //delete the serialization file
			serFile = null;
													 			
		}
		catch(Throwable e)
		{
			System.out.println("de-Serialization " + e.getMessage() + e);
			e.printStackTrace();
		}
	}

}

class MyAction extends AbstractAction
{
	MyAction(String str)
	{
		super(str);
	}

	public void actionPerformed(ActionEvent arg0)
	{
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Create the JMenu object using the String constructor JMenu(String strAction)

Comments
EVALUATION This was fixed as part of 4626632. Refer to it for details.
12-07-2006

EVALUATION Like with 6442684, I can reproduce the reported deserialization exception with 5.0, but not with Mustang, and the reason is similar: In 5.0, JMenuItem.MenuItemActionPropertyChangeListener implemented Serializable directly, and its superclass, AbstractActionPropertyChangeListener, did not implement Serializable and did not provide a no-arg constructor-- hence the deserializaion failure. In Mustang, ActionPropertyChangeListener implements Serializable and extends Object (which provides an appropriate constructor for the first non-Serializable superclass), so the deserialization failure does not occur. I am recategorizing this CR to java/classes_swing to evaluate the issue for the sake of 5.0 update releases.
23-06-2006