Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: EE-3.0.0.GA
-
Fix Version/s: 3.1.0.BETA2, 3.1
-
Component/s: ACE-Components
-
Labels:None
-
Environment:All
-
Assignee Priority:P2
Description
An ace:dataTable is set to be filterable. This table includes a column that has a commandLink that uses an f:attribute or f:setPropertyActionListener so that row level information can be passed in. This works fine on the initial rendering of the table. Once a column is filtered and the order of rows is changed the value retrieved from the f:attribute or f:setPropertyActionListener is not the one that corresponds with the visible row.
-
- Case11152Example.zip
- 18 kB
- Arran Mccullough
-
Hide
- Case11152Example.war
- 9.39 MB
- Arran Mccullough
-
- META-INF/MANIFEST.MF 0.1 kB
- META-INF/context.xml 0.1 kB
- WEB-INF/classes/test/Bean.class 2 kB
- WEB-INF/classes/test/Entity.class 0.8 kB
- WEB-INF/classes/test/EntityService.class 1 kB
- WEB-INF/lib/commons-beanutils.jar 226 kB
- WEB-INF/lib/commons-collections.jar 558 kB
- WEB-INF/lib/commons-digester.jar 140 kB
- WEB-INF/lib/commons-logging.jar 52 kB
- WEB-INF/lib/icefaces-ee-ace.jar 1.46 MB
- WEB-INF/lib/icefaces-ee-compat.jar 2.57 MB
- WEB-INF/lib/icefaces-ee-ext.jar 56 kB
- WEB-INF/lib/icefaces-ee.jar 271 kB
- WEB-INF/lib/javax.faces.jar 2.47 MB
- WEB-INF/lib/poi-3.7.jar 1.60 MB
- WEB-INF/web.xml 2 kB
- welcomeICEfaces.xhtml 2 kB
Activity
- All
- Comments
- History
- Activity
- Remote Attachments
- Subversion
My suspicion is that this is due to the data model being generated (via getDataModel()) with a list that is not the filtered list(via getValue()), even though we have a filtered list in our state we should be exposing.
This is usually due to our state saving breaking because the table clientId contains iterative indexes. When getFilteredData() is called is called in getValue(), null is returned (because the state doesn't exist for the incorrect clientId) and the UIData implementation of getValue() supplies the backing for the data model.
Up until now, our solution for this issue has been putting off fixing it at large and simply avoiding it and not calling methods that access the component state (as held by the meta class generated properties) during an iterative context. However this appears to be a framework initiated instance where we need that state during iteration, and I'm not sure how we're to work around it.
The implementation of f:setPropertyActionListener is very simple: for this page we have
<ace:dataTable value="#
{bean.data}" var="entity">
and setPropertyActionListener evaluates #
{entity}at
at com.sun.faces.facelets.tag.jsf.core.SetPropertyActionListenerHandler$SetPropertyListener.processAction(SetPropertyActionListenerHandler.java:209)
at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:769)
at javax.faces.component.UICommand.broadcast(UICommand.java:300)
at javax.faces.component.UIData.broadcast(UIData.java:1093)
at org.icefaces.ace.component.datatable.DataTable.broadcast(DataTable.java:222)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
The relevant code in UIData is:
FacesContext context = FacesContext.getCurrentInstance();
// Set up the correct context and fire our wrapped event
WrapperEvent revent = (WrapperEvent) event;
if (isNestedWithinUIData())
int oldRowIndex = getRowIndex();
setRowIndex(revent.getRowIndex());
FacesEvent rowEvent = revent.getFacesEvent();
UIComponent source = rowEvent.getComponent();
UIComponent compositeParent = null;
try {
if (!UIComponent.isCompositeComponent(source))
if (compositeParent != null)
{ compositeParent.pushComponentToEL(context, null); } source.pushComponentToEL(context, null);
source.broadcast(rowEvent);
It looks like UIData calls getRowIndex() – does our DataTable return the rowIndex into the filtered data or into the unfiltered data? It also looks like we have an opportunity during broadcast() to filter the data rather than calling
setDataModel(null);
Judging from:
int oldRowIndex = getRowIndex();
setRowIndex(revent.getRowIndex());
The data table probably has an iterative ID because it has a pre-existing row index that needs saving. When an iterative ID is set, the generator properties don't work correctly, so the unfiltered dataset is being referenced.
I suppose the only fixes are to override the UIData broadcast behaviour or fix generator properties.
Revision #29269
Committed by nils.lundquist
A minute ago
ICE-8098 - Overrode UIData.broadcast() in ace:datatable to correct clientId before accessing filtered state.
Attached test case that shows the issue with f:setPropertyActionListener. The f:attribute implementation is commented out.
Steps to reproduce: