Possible bug: When editing a table produced with GlazedListsSwing.eventTableModelWithThreadProxyList(EventList, String[], String[], boolean[]) an exception occurs with int type

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Possible bug: When editing a table produced with GlazedListsSwing.eventTableModelWithThreadProxyList(EventList, String[], String[], boolean[]) an exception occurs with int type

gregorypeckdom
This post has NOT been accepted by the mailing list yet.
When editing a table created with GlazedListsSwing.eventTableModelWithThreadProxyList(EventList, String[], String[], boolean[]) an exception occurs when editing an int type column. It is interesting that the exception does not occur if you use the GlazedListsSwing.eventTableModelWithThreadProxyList(EventList, TableFormat) method.

Exception trace:
Exception in thread "AWT-EventQueue-0" java.lang.InternalError: Malformed class name
        at ca.odell.glazedlists.impl.beans.BeanProperty.getSimpleName(BeanProperty.java:328)
        at ca.odell.glazedlists.impl.beans.BeanProperty.set(BeanProperty.java:294)
        at ca.odell.glazedlists.impl.beans.BeanTableFormat.setColumnValue(BeanTableFormat.java:179)
        at ca.odell.glazedlists.swing.DefaultEventTableModel.setValueAt(DefaultEventTableModel.java:245)
        at javax.swing.JTable.setValueAt(JTable.java:2740)
        at javax.swing.JTable.editingStopped(JTable.java:4722)
        at javax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:141)
        at javax.swing.DefaultCellEditor$EditorDelegate.stopCellEditing(DefaultCellEditor.java:368)
        at javax.swing.DefaultCellEditor.stopCellEditing(DefaultCellEditor.java:233)
        at javax.swing.JTable$GenericEditor.stopCellEditing(JTable.java:5477)
        at javax.swing.DefaultCellEditor$EditorDelegate.actionPerformed(DefaultCellEditor.java:385)
        at javax.swing.JTextField.fireActionPerformed(JTextField.java:508)
        at javax.swing.JTextField.postActionEvent(JTextField.java:721)
        at javax.swing.JTextField$NotifyAction.actionPerformed(JTextField.java:836)
        at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1664)
        at javax.swing.JComponent.processKeyBinding(JComponent.java:2879)
        at javax.swing.JComponent.processKeyBindings(JComponent.java:2926)
        at javax.swing.JComponent.processKeyEvent(JComponent.java:2842)
        at java.awt.Component.processEvent(Component.java:6282)
        at java.awt.Container.processEvent(Container.java:2229)
        at java.awt.Component.dispatchEventImpl(Component.java:4861)
        at java.awt.Container.dispatchEventImpl(Container.java:2287)
        at java.awt.Component.dispatchEvent(Component.java:4687)
        at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1895)
        at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:762)
        at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1027)
        at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:899)
        at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:727)
        at java.awt.Component.dispatchEventImpl(Component.java:4731)
        at java.awt.Container.dispatchEventImpl(Container.java:2287)
        at java.awt.Window.dispatchEventImpl(Window.java:2719)
        at java.awt.Component.dispatchEvent(Component.java:4687)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:729)
        at java.awt.EventQueue.access$200(EventQueue.java:103)
        at java.awt.EventQueue$3.run(EventQueue.java:688)
        at java.awt.EventQueue$3.run(EventQueue.java:686)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
        at java.awt.EventQueue$4.run(EventQueue.java:702)
        at java.awt.EventQueue$4.run(EventQueue.java:700)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:699)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

Source code used to produce this:
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.swing.AdvancedTableModel;
import ca.odell.glazedlists.swing.GlazedListsSwing;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;

/**
 * When editing the table produced through
 * {@link GlazedListsSwing#eventTableModelWithThreadProxyList
 * (ca.odell.glazedlists.EventList, java.lang.String[], java.lang.String[], boolean[]) }
 * An exception occurs after editing an int column.
 */
public class GlazedIntBug extends JFrame{
    public static class Wrapper{
        private int value;

        public Wrapper(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }
        
    }
    
    public GlazedIntBug(){
        //set up the event list
        EventList<Wrapper> list = GlazedLists.eventListOf(
                new Wrapper(1), new Wrapper(2), new Wrapper(3));
        String [] props = {"value"};
        String [] names = {"Value"};
        boolean [] write = {true};
        
        //This is the code that produces the bug
        AdvancedTableModel<Wrapper> model = 
                    GlazedListsSwing.eventTableModelWithThreadProxyList(
                        list, props, names, write);
        JTable table1 = new JTable(model);
        
        //This works OK
        TableFormat<Wrapper> format = 
                GlazedLists.tableFormat(Wrapper.class, props, names, write);
        AdvancedTableModel<Wrapper> model2 =
                GlazedListsSwing.eventTableModelWithThreadProxyList(list, format);
        JTable table2 = new JTable(model2);
        
        //now finish the UI
        JScrollPane pane1 = new JScrollPane(table1);
        JScrollPane pane2 = new JScrollPane(table2);
        
        this.add(pane1, BorderLayout.WEST);
        this.add(pane2, BorderLayout.EAST);
        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        new GlazedIntBug().setVisible(true);
    }
}
Reply | Threaded
Open this post in threaded view
|

Re: Possible bug: When editing a table produced with GlazedListsSwing.eventTableModelWithThreadProxyList(EventList, String[], String[], boolean[]) an exception occurs with int type

hbrands
Administrator
This post has NOT been accepted by the mailing list yet.
What happens is the following:

GlazedListsSwing.eventTableModelWithThreadProxyList(EventList, String[], String[], boolean[]) constructs an TableFormat internally via GlazedLists.tableFormat(String[], String[], boolean[]), e.g. without the bean class (Wrapper.class). That's the important difference. Without knowing the bean class, the BeanTableFormat can only return Object.class for the column class. As a consequence the default editor for Object.class is used (JTable.GenericEditor in my case), which treats the value as String, not as int or Integer.
So the BeanProperty gets a string value as input and tries to call the Wrapper.setValue method with it as parameter, which results in a IllegalArgumentException:
java.lang.IllegalArgumentException: Wrapper.setValue(int) cannot be called with an instance of String
(There is a bug in the BeanProperty.getSimpleName method which hides the real cause)

In summary: use GlazedLists.tableFormat(Class, String[], String[], boolean[]) instead of GlazedLists.tableFormat(String[], String[], boolean[]) when some of the columns are editable and not of type String.
I think we should clarify the JavaDoc in this regard.

Hope this helps,
Holger

P.S.: please post to the Glazed Lists mailing list directly, otherwise we don't get notified. Posting via Nabble does not push through to the mailing list unfortunately.