-
Bug
-
Resolution: Cannot Reproduce
-
P4
-
6, 7
-
x86
-
windows_7
FULL PRODUCT VERSION :
java version "1.7.0_07"
Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
Java HotSpot(TM) 64-Bit Server VM (build 23.3-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
When using a RowSorter on a JTable with one row which has that row selected, changing the RowFilter to one which hides all the selected rows and then removing the row causes an ArrayIndexOutOfBoundsException.
JTable.SortManager appears to keep a cache of the current selection in terms of model rows; this allows it to restore the previous selection if you change the filter without changing the selection. However, the logic that uses this to restore the selection appears to be flawed. The restoreSelection method assumes that the leadSelectionIndex is a valid model index if it is not -1; however, the lead selection index is not bound to be within the existing model elements (e.g. removeIndexInterval in DefaultListSelectionModel can cause the lead and anchor to remain at 0 when the last row is removed). I'm not completely sure if this is a bug in DefaultListSelectionModel or SortManager, since the behaviour of the lead and anchor selection indices aren't specified very well in ListSelectionModel.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test case listed below.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No exception occurs
ACTUAL -
An ArrayIndexOutOfBoundsException occurs
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at javax.swing.DefaultRowSorter.convertRowIndexToView(DefaultRowSorter.java:503)
at javax.swing.JTable.convertRowIndexToView(JTable.java:2623)
at javax.swing.JTable$SortManager.restoreSelection(JTable.java:4048)
at javax.swing.JTable$SortManager.processChange(JTable.java:4000)
at javax.swing.JTable.sortedTableChanged(JTable.java:4132)
at javax.swing.JTable.tableChanged(JTable.java:4398)
at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
at javax.swing.table.AbstractTableModel.fireTableRowsDeleted(AbstractTableModel.java:261)
at javax.swing.table.DefaultTableModel.removeRow(DefaultTableModel.java:464)
at SortTest.main(SortTest.java:24)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
public class SortTest
{
public static void main( final String[] args )
{
DefaultTableModel model = new DefaultTableModel( new Object[] { "column" }, 1 );
TableRowSorter< DefaultTableModel > sorter = new TableRowSorter< DefaultTableModel >( model );
JTable table = new JTable( model );
table.setRowSorter( sorter );
table.getSelectionModel().setSelectionInterval( 0, 0 );
sorter.setRowFilter( new RowFilter< DefaultTableModel, Object >()
{
@Override
public boolean include( final Entry< ? extends DefaultTableModel, ? extends Object > entry )
{
return false;
}
} );
model.removeRow( 0 );
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
I've not found a workable one yet; I'm still hunting for one.
java version "1.7.0_07"
Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
Java HotSpot(TM) 64-Bit Server VM (build 23.3-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
When using a RowSorter on a JTable with one row which has that row selected, changing the RowFilter to one which hides all the selected rows and then removing the row causes an ArrayIndexOutOfBoundsException.
JTable.SortManager appears to keep a cache of the current selection in terms of model rows; this allows it to restore the previous selection if you change the filter without changing the selection. However, the logic that uses this to restore the selection appears to be flawed. The restoreSelection method assumes that the leadSelectionIndex is a valid model index if it is not -1; however, the lead selection index is not bound to be within the existing model elements (e.g. removeIndexInterval in DefaultListSelectionModel can cause the lead and anchor to remain at 0 when the last row is removed). I'm not completely sure if this is a bug in DefaultListSelectionModel or SortManager, since the behaviour of the lead and anchor selection indices aren't specified very well in ListSelectionModel.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test case listed below.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No exception occurs
ACTUAL -
An ArrayIndexOutOfBoundsException occurs
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at javax.swing.DefaultRowSorter.convertRowIndexToView(DefaultRowSorter.java:503)
at javax.swing.JTable.convertRowIndexToView(JTable.java:2623)
at javax.swing.JTable$SortManager.restoreSelection(JTable.java:4048)
at javax.swing.JTable$SortManager.processChange(JTable.java:4000)
at javax.swing.JTable.sortedTableChanged(JTable.java:4132)
at javax.swing.JTable.tableChanged(JTable.java:4398)
at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
at javax.swing.table.AbstractTableModel.fireTableRowsDeleted(AbstractTableModel.java:261)
at javax.swing.table.DefaultTableModel.removeRow(DefaultTableModel.java:464)
at SortTest.main(SortTest.java:24)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
public class SortTest
{
public static void main( final String[] args )
{
DefaultTableModel model = new DefaultTableModel( new Object[] { "column" }, 1 );
TableRowSorter< DefaultTableModel > sorter = new TableRowSorter< DefaultTableModel >( model );
JTable table = new JTable( model );
table.setRowSorter( sorter );
table.getSelectionModel().setSelectionInterval( 0, 0 );
sorter.setRowFilter( new RowFilter< DefaultTableModel, Object >()
{
@Override
public boolean include( final Entry< ? extends DefaultTableModel, ? extends Object > entry )
{
return false;
}
} );
model.removeRow( 0 );
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
I've not found a workable one yet; I'm still hunting for one.