Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Cannot Reproduce
-
Affects Version/s: EE-2.0.0
-
Fix Version/s: EE-3.2.0.GA
-
Component/s: Facelet Components
-
Labels:None
-
Environment:All
-
Assignee Priority:P1
-
Salesforce Case Reference:
-
Workaround Exists:Yes
-
Workaround Description:Call FacesContext.getCurrentInstance().getViewRoot().getChildren().clear() before rendering the 2nd table.
Description
Two tables (richDataGrid) can show data. These tables are not shown immediately so they are initialized with dummy data. When the tables are required to be shown they are re-initialized with a new column array and a new set of data. The tables are shown one at a time. The issue arises once one table is shown, then another table is rendered. The first table that is rendered then is displayed with either a duplication of columns or is missing columns from when it was first displayed.
This issue also depends on how the tables are defined in the page. For example, table #1 is displayed first then table #2. If table #2 is rendered first, then table #1, this issue is shown. If table #1 is shown then table #2, this issue does not occur. It also seems to occur on the first rendering of the tables. If the tables are opened in the order that does not show the issue, displaying the tables after using the order that causes the issue does not reproduce the issue.
Upon further analysis this issue seems to be due to the re-initialization of the RichDataGridBean object with a new column array. In my test case if I re-use the same column array from when it was first initialized, I can't reproduce the issue. This could be a potential workaround as long as the same column list can be used for the data once it has been re-initialized.
-
Hide
- Case10062Example4.war
- 6.79 MB
- Arran Mccullough
-
- META-INF/MANIFEST.MF 0.1 kB
- META-INF/context.xml 0.1 kB
- WEB-INF/classes/.../example/Employee.class 2 kB
- WEB-INF/.../TableControllerBean.class 3 kB
- WEB-INF/.../TestBean$MyTableEventListener.class 2 kB
- WEB-INF/classes/.../example/TestBean.class 5 kB
- WEB-INF/.../TestBeanNew$MyTableEventListener.class 2 kB
- WEB-INF/classes/.../TestBeanNew.class 5 kB
- WEB-INF/faces-config.xml 1 kB
- WEB-INF/lib/commons-beanutils.jar 226 kB
- WEB-INF/lib/commons-digester.jar 140 kB
- WEB-INF/lib/commons-logging.jar 52 kB
- WEB-INF/lib/icefaces-ee-compat.jar 2.67 MB
- WEB-INF/lib/icefaces-ee-composite.jar 357 kB
- WEB-INF/lib/icefaces-ee.jar 206 kB
- WEB-INF/lib/jsf-api.jar 602 kB
- WEB-INF/lib/jsf-impl.jar 1.81 MB
- WEB-INF/lib/jstl.jar 20 kB
- WEB-INF/lib/jxl.jar 708 kB
- WEB-INF/lib/wyswyg-appbase.jar 22 kB
- WEB-INF/web.xml 2 kB
- welcomeICEfaces.xhtml 2 kB
-
Hide
- Case10062Example4.zip
- 22 kB
- Arran Mccullough
-
- Case10062Example4/build.xml 3 kB
- Case10062Example4/.../ant-deploy.xml 2 kB
- Case10062Example4/.../build-impl.xml 55 kB
- Case10062Example4/.../faces-config.NavData 0.3 kB
- Case10062Example4/.../genfiles.properties 0.5 kB
- Case10062Example4/.../private.properties 0.5 kB
- Case10062Example4/nbproject/.../private.xml 0.2 kB
- Case10062Example4/.../project.properties 4 kB
- Case10062Example4/nbproject/project.xml 3 kB
- Case10062Example4/src/conf/MANIFEST.MF 0.0 kB
- Case10062Example4/src/.../Employee.java 2 kB
- Case10062Example4/.../TableControllerBean.java 2 kB
- Case10062Example4/src/.../TestBean.java 6 kB
- Case10062Example4/src/.../TestBeanNew.java 6 kB
- Case10062Example4/web/.../context.xml 0.1 kB
- Case10062Example4/web/.../faces-config.xml 1 kB
- Case10062Example4/web/WEB-INF/web.xml 2 kB
- Case10062Example4/.../welcomeICEfaces.xhtml 2 kB
-
Hide
- datagridtest.war
- 6.63 MB
- Philip Breau
-
- META-INF/MANIFEST.MF 0.0 kB
- WEB-INF/classes/.../example/Employee.class 2 kB
- WEB-INF/.../TableControllerBean.class 3 kB
- WEB-INF/.../TestBean$MyTableEventListener.class 2 kB
- WEB-INF/classes/.../example/TestBean.class 6 kB
- WEB-INF/.../TestBeanNew$MyTableEventListener.class 2 kB
- WEB-INF/classes/.../TestBeanNew.class 6 kB
- WEB-INF/faces-config.xml 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-compat.jar 2.57 MB
- WEB-INF/lib/icefaces-ee-composite.jar 367 kB
- WEB-INF/lib/icefaces-ee.jar 270 kB
- WEB-INF/lib/javax.faces.jar 2.47 MB
- WEB-INF/lib/jstl.jar 20 kB
- WEB-INF/lib/jxl.jar 708 kB
- WEB-INF/web.xml 2 kB
- welcomeICEfaces.xhtml 2 kB
-
Hide
- dgTest.zip
- 6.64 MB
- Philip Breau
-
- dgTest/.classpath 0.8 kB
- dgTest/.project 1.0 kB
- dgTest/.settings/.jsdtscope 0.5 kB
- dgTest/.../org.eclipse.jdt.core.prefs 0.4 kB
- dgTest/.../org.eclipse.wst.common.component 0.5 kB
- dgTest/.../org.eclipse.wst.common.project.facet.core.xml 0.3 kB
- dgTest/.../org.eclipse.wst.jsdt.ui.superType.container 0.0 kB
- dgTest/.../org.eclipse.wst.jsdt.ui.superType.name 0.0 kB
- dgTest/WebContent/META-INF/MANIFEST.MF 0.0 kB
- dgTest/WebContent/.../faces-config.xml 1 kB
- dgTest/WebContent/.../commons-beanutils.jar 226 kB
- dgTest/.../commons-collections.jar 558 kB
- dgTest/WebContent/.../commons-digester.jar 140 kB
- dgTest/WebContent/.../commons-logging.jar 52 kB
- dgTest/WebContent/.../icefaces-ee-compat.jar 2.57 MB
- dgTest/.../icefaces-ee-composite.jar 367 kB
- dgTest/WebContent/.../lib/icefaces-ee.jar 270 kB
- dgTest/WebContent/.../lib/javax.faces.jar 2.47 MB
- dgTest/WebContent/WEB-INF/lib/jstl.jar 20 kB
- dgTest/WebContent/WEB-INF/lib/jxl.jar 708 kB
- dgTest/WebContent/WEB-INF/web.xml 2 kB
- dgTest/WebContent/welcomeICEfaces.xhtml 2 kB
- dgTest/build/.../example/Employee.class 2 kB
- dgTest/build/.../TableControllerBean.class 3 kB
- dgTest/.../TestBean$MyTableEventListener.class 2 kB
- dgTest/build/.../example/TestBean.class 6 kB
- dgTest/.../TestBeanNew$MyTableEventListener.class 2 kB
- dgTest/build/.../example/TestBeanNew.class 6 kB
- dgTest/src/com/.../example/Employee.java 2 kB
- dgTest/src/.../TableControllerBean.java 3 kB
Activity
- All
- Comments
- History
- Activity
- Remote Attachments
- Subversion
I would mark this as invalid if the column restructuring is done through manipulating the array returned from RichDataGrid.getColumns(). The component bean is designed to be immutable, so if the user needs to dynamically alter the column structure, a new instance of the bean should be created by calling the constructor again. I have updated the bean, so that a safe copy of the column structure is returned by RichDataGrid.getColumns() preventing any changes to the initial column structure.
I've added the following method that can be used instead of manually manipulating the column array structure:
/**
- Returns a copy of the RichDataGridBean with a new column structure.
- @param columns The new column structure
- @return a new copy of the bean with the new column structure
*/
public RichDataGridBean cloneWithNewColumnStructure(IRichDataColumn[] columns)
getColumns() was not being called. The issue might be due to c:forEach in the composite component not being re-resolved.
simplified test case
Simplified test case shows correct behaviour
source
The workaround mentioned does not fulfill the requirements of the application using this so that isn't a valid workaround for the issue.
Thanks for the source code. My test case had a slightly different setup in the backing beans. I've been able to narrow down the scenario where this issue is still seen. The main issue with my test case seems to be related to two things:
- The usage of the RichDataTextColumn shownByDefault object to hide/show the column.
- The order in how the tables are rendered on the page.
In your attached test case you just use the basic constructor for the RichDataTextColumn object. In my test case it uses the more fine grained one which gives control over if its editable, shown, etc. I found that if I used the same basic constructor but also changed the number of columns that were rendered for each table it worked well without seeing the issue.
Using the larger constructor doesn't seem to be the only factor, it also depends on the order they are rendered on the page in relation to where they are defined in the source code of the page.
For example, in the source code I have the "New" table defined first and then the "Existing" table defined next. If I click the button to show the "New" table and then the "Existing" table, the columns for each one render fine with no missing or duplicated tables. Going the other way, rendering the "Existing" table then the "New" table causes the "Existing table to lose some columns and also have it duplicate the columns.
Looking at the response for this scenario, for some reason when the "New" table is added, the "Existing" table also gets updated even though it hasn't changed and the action is done on a completely different bean.
I'm checking to see if there are some workarounds that involve using an <f:ajax> so that only a section of the page is updated instead of the entire form. I should also note that I don't see the same issue with the order of rendering when using the basic constructor. I'm also using the cloneWithNewColumnStructure() method.
So there would be two potential workarounds:
- Use the basic constructor for the RichDataTextColumn objects.
- Control how the tables are rendered on the page.
Using an <h:commandButton> that uses an <f:ajax>tag and also testing on the final ICEfaces EE 3.0 release looks to have helped to resolve the remaining issue that I have seen. I replaced the ice:commandButton that toggled the display of the richDataGrid with an h:commandButton that uses an f:ajax tag to render only the panel that surrounds the richDataGrid component. This prevents the update from affecting the other richDataGrid.
Here is the code I've been testing:
<h:form id="iceForm">
<h:panelGroup id="newPanel">
<ice:commandButton value="Show New - ICE" actionListener="#
<h:commandButton value="Show New - JSF" actionListener="#{testBeanNew.resetList}
">
<f:ajax execute="@this" render="iceForm:newPanel"/>
</h:commandButton>
<ice:panelGroup rendered="#
">
<ice:outputText value="New Table"/>
<ice-cc:richDataGrid bean="#
"
id="richDataGridNew"
/>
</ice:panelGroup>
</h:panelGroup>
<h:panelGroup id="existingPanel">
<ice:commandButton value="Show Existing - ICE" actionListener="#
<h:commandButton value="Show Existing - JSF" actionListener="#{testBeanExisting.resetList}
">
<f:ajax execute="@this" render="iceForm:existingPanel"/>
</h:commandButton>
<ice:panelGroup rendered="#
">
<ice:outputText value="Existing Table"/>
<ice-cc:richDataGrid bean="#
"
id="richDataGridExisting"
/>
</ice:panelGroup>
</h:panelGroup>
</h:form>
When using the ice:commandButton's and showing the "Existing" table first and then the "New" table, the "Existing" table columns would be not correct. When using the h:commandButton's in the same way, the "Existing" table keeps its correct set of columns as the update doesn't effect this panel.
The problem initially occurred when logic triggered while clicking on ice:treeNode which cannot be replaced with an h:commandButton so I don't understand how that work around will correct this issue.
What happens was the user clicks on this tree node which brings up either one or both richdatagrids based on some conditions. Intermittently this duplicate column issue would appear when that occurs. I don't know if the test case has been simplified too much which removes the treeNode but that is an integral part of the application and cannot be replaced with a button.
Upon investigation I noticed that many autogenerated jsf component ids were changing at the rerendering of the new data grid. I've added more explicitly set dynamic id's to the sub components of the rich data grid to avoid this, although the update issue is still happening.
The column data on the server appears to be correct. On clicking the 'Show New' button to render the new table, the columns of the existing table are resolved to be the following (column name, visibility state):
columns [ id:true, firstName:true, lastName:true, dept:true, section:false, company:false ]
I've ruled out partial update anomalies. The DOM updates are being reconstructed properly, although the DOM updates themselves are being generated incorrectly. eg: one of the updates occurring on the rerendering of the new table is the following column data:
<div class="icePnlGrp richDatGrdCol"
id="iceForm:richDataGridNew_subview:richDataGridNew:1:id_text_ctr"
oncontextmenu="Ice.Menu.contextMenuPopup(event,
'iceForm:richDataGridNew_subview:richDataGridNew:1:createRowMenu_sub',
'iceForm:richDataGridNew_subview:richDataGridNew:1:id_text_ctr');return
false;"
style="width:;">
<span class="iceOutTxt"
id="iceForm:richDataGridNew_subview:richDataGridNew:1:id_text_ro"
title="Johnson">Johnson</span>
</div>
Looking at the update, this is the last name cell value of 'Johnson'. Although the id's are incorrect. The id 'iceForm:richDataGridNew_subview:richDataGridNew:1:id_text_ro' should belong to the cell of the second row first column, named 'id', a text column, in the read only state. So, it appears that the outputText for the 'id' column, has the value set for the last name column.
So, since this doesn't appear to be a partial update or DOM diff issue, it points to a state saving issue on the component level. Further investigation is required. An interim workaround that could be provided very quickly is creating a 2nd separate richDataGrid component, with a different set of internally rendering id's, which may, perhaps, shield the components from any variable scoping issues.
Still looking for a solution to this, although the issue still appears to be a JSTL scoping and possibly a JSF component id issue. One current simple workaround is to call FacesContext.getCurrentInstance().getViewRoot().getChildren().clear(); before rendering the second table:
class TestBeanNew{
...
public void resetList(ActionEvent event)
...
}
Clearing the JSF component children of the panelGroup containing the new data grid In the test case should also be a workaround.
All of the workarounds suggested either don't satisfy the requirements or they don't work. I see the latest EE release was added to the end of this but the issue is still open. Does that mean that code changes were actually made in 3.0.0.GA_P01 and it works or does that mean just try one of the workarounds that doesn't work?
Retested on ICEfaces EE 3 rev 33253 with or without the workaround. Note that this build is now using Mojarra 2.1.17, which includes state saving bug fixes that have may have been the root issue here.
Steps to reproduce issue: