Sending this again with the proper heading: By default, when Java Lists/Arrays are used as models in Trinidad table/tree/treeTable components, they are wrapped in a SortableModel instance.
The problem with SortableModel is that it uses row indexes as row keys. This makes SortableModel immutable and insert/delete operations in the underlying List/array can cause problems. For example, indexes shift after insert/delete operations and can cause problems if the component is holding on to row keys in SelectedRowKey/DisclosedRowKey sets. The proposal is to add row key based CollectionModel/TreeModels which avoid using indexes as row keys. (See below). One drawback with the implementation of setRowKey API in RowKeyPropertyModel (below) is that it is inefficient for large Lists and does a linear search through the model to find the row with the given row key. 1) Add a RowKeyPropertyModel which extends SortableModel and uses row keys instead of indexes: package org.apache.myfaces.trinidad.model; /** * Creates a CollectionModel whose row keys are defined by a unique data property in the model. */ public class RowKeyPropertyModel extends SortableModel { /** * Creates a RowKeyPropertyModel. * * @param model The underlying model. If necessary, this will be converted into a {...@link DataModel} * @param rowKeyProperty The property by which the row key can be accessed. Row key value must be unique */ public RowKeyPropertyModel(Object model, String rowKeyProperty) { super(model); _rowKeyProperty = rowKeyProperty; } /** * No arg constructor for use as a managed-bean. * Must call {...@link #setWrappedData} and {...@link #setRowKeyProperty} before using this instance. */ public RowKeyPropertyModel() { super(); } /** * Gets the row key for the current row * @return row key or null if model is not on any row */ public Object getRowKey() { if (isRowAvailable()) { Object rowKey = _getRowKey(); return rowKey; } else { return null; } } public void setRowKey(Object key) { if (key == null) { setRowIndex(-1); return; } if (getRowKey() != null && getRowKey().equals(key)) return; for (int i = 0; i < getRowCount(); i++) { setRowIndex(i); Object prop = getRowKey(); if (key.equals(prop)) { return; } } // if we didn't find an element with a matching key, // then don't make any rows current setRowIndex(-1); } /** * Gets the row key property name for this model * @return row key property name */ public String getRowKeyProperty() { return _rowKeyProperty; } /** * Sets the row key property for this model * @param rowKeyProperty row key property to set */ public void setRowKeyProperty(String rowKeyProperty) { _rowKeyProperty = rowKeyProperty; } /** * gets the row key for the given row by resolving the _rowKeyProperty * @param row row to retrieve the row key for * @return row key value */ protected Object getRowKey(Object row) { return __resolveProperty(row, _rowKeyProperty); } /** * gets the row key for current row by resolving the _rowKeyProperty * @return */ private Object _getRowKey() { Object data = getRowData(); return __resolveProperty(data, _rowKeyProperty); } private String _rowKeyProperty; } 2) Add a RowKeyPropertyTreeModel which extends ChildPropertyTreeModel and wraps each child model with a RowKeyPropertyModel: package org.apache.myfaces.trinidad.model; /** * A subclass of {...@link ChildPropertyTreeModel} that supports row keys by creating * {...@link RowKeyPropertyModel}(s) for its child models. * * Ooverrides the protected createChildModel method in {...@link ChildPropertyTreeModel} so that it can instantiate * RowKeyPropertyModels as it encounters child data. */ public class RowKeyPropertyTreeModel extends ChildPropertyTreeModel { /** * Creates a RowKeyPropertyTreeModel * * @param model The underlying model. This will be converted into a {...@link DataModel} * @param childProperty The property by which the child data can be accessed. * @param rowKeyProperty The property by which the row key can be accessed. */ public RowKeyPropertyTreeModel(Object model, String childProperty, String rowKeyProperty) { super (new RowKeyPropertyModel(model, rowKeyProperty), childProperty); _rowKeyProperty = rowKeyProperty; } /** * No-arg constructor for use with managed-beans. * Must call the {...@link #setChildProperty}, * {...@link #setWrappedData} and {...@link #setRowKeyProperty} methods after constructing this instance. */ public RowKeyPropertyTreeModel() { super(); } /** * Overrides ChildPropertyTreeModel.createChildModel(). * Converts childData into a RowKeyPropertyModel. * * @param childData the data to convert. This can be a List or array. */ @Override protected CollectionModel createChildModel(Object childData) { CollectionModel model = new RowKeyPropertyModel(childData, _rowKeyProperty); model.setRowIndex(-1); return model; } /** * Gets the row key property name for this model * @return row key property name */ public String getRowKeyProperty() { return _rowKeyProperty; } /** * Sets the row key property for this model * @param rowKeyProperty row key property to set */ public void setRowKeyProperty(String rowKeyProperty) { _rowKeyProperty = rowKeyProperty; } private String _rowKeyProperty = null; } Thanks Kamran