Duplicate component ID on components with binding
jeff.haynes1 Jun 22, 2009 1:00 PMI've come across a very frustrating problem and I'm hoping that somebody here can point me in the right direction to a fix.
I noticed the problem when I was trying to create a user list that would be included in a side navigation panel on any/all various pages of the website. The user list was created with a <rich:dataTable /> tag, and populated with a list of users from our database. The list can be sorted, filtered, and the <rich:datascroller /> was used to paginate between pages of 10 users each.
I bound the dataTable to a session-scoped backing bean (not SFSB) in jorder to maintain state of the table throughout a user's session, especially if they hide the user table or navigate to a completely different page and then back (I want the selected page, sort order, etc. to remain as it was set by the user for the duration of their session.)
Pretty straight-forward stuff, but the problem comes when this user table is rendered on a *different view* - i.e. if the table is first rendered on home.xhtml when the user logs in, and then they navigate to another view that includes the list, say profile.xhtml, the following exception is thrown:
11:58:16,937 ERROR [viewhandler] Error Rendering View[/user.xhtml]
java.lang.IllegalStateException: duplicate Id for a component navUserListForm:navUserListTable:firstNameCol
at org.ajax4jsf.application.TreeStructureNode.apply(TreeStructureNode.java:68)
at org.ajax4jsf.application.TreeStructureNode.apply(TreeStructureNode.java:92)
at org.ajax4jsf.application.TreeStructureNode.apply(TreeStructureNode.java:92)
at org.ajax4jsf.application.TreeStructureNode.apply(TreeStructureNode.java:92)
at org.ajax4jsf.application.TreeStructureNode.apply(TreeStructureNode.java:92)
at org.ajax4jsf.application.TreeStructureNode.apply(TreeStructureNode.java:92)
at org.ajax4jsf.application.AjaxStateManager.getTreeStructureToSave(AjaxStateManager.java:187)
at org.ajax4jsf.application.AjaxStateManager.buildViewState(AjaxStateManager.java:498)
at org.ajax4jsf.application.AjaxStateManager$SeamStateManagerWrapper.saveView(AjaxStateManager.java:105)
at org.jboss.seam.jsf.SeamStateManager.saveView(SeamStateManager.java:89)
at org.ajax4jsf.application.AjaxStateManager.saveSerializedView(AjaxStateManager.java:454)
at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:615)
at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:368)
at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:495)
at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:601)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
After a bit (well, quite a lot) of searching, I came across JIRA 2218 https://jira.jboss.org/jira/browse/RF-2218 which seemed pretty close to the problem I was seeing. When I have a component that is bound to a backing bean, I will get the duplicate id exception if I navigate to another page that includes that component. If I remove the binding, I can navigate between the pages that include the component, but the state of the selected page, column sort order, etc. will be lost and the table will be reset on each page.
In the JIRA, Nick points to an issue in the JSF-API implementation that is related to removing old children from the render tree, and suggests setting the context param org.ajax4jsf.SERIALIZE_SERVER_STATE to true as a workaround.
My issue is, this workaround does not seem to correct the problem I'm seeing with the environment I'm using:
jboss-5.0.1.GA
jboss-seam-2.1.2
jboss-richfaces-3.3.1.GA
WinXP Professional 2002 SP3
After doing a lot of testing and code traces, I found that the last bound component in a tree has its children duplicated on each disparate view. This problem occurs with many of the components that I tested - dataTable, dataList, panels, etc.
At this point, I'm stuck and pretty sure that the problem is either:
1. I'm totally missing something, and implementing my JSF application pages incorrectly
2. There is still a problem in jsf-api.jar (seems to be in UIComponentBase to me now) that is affecting any Richfaces or plain JSF application in a majorly detrimental way
I'm hoping that it's #1 above, and somebody out there can give me that magic little setting that will make this problem go away. However, after a couple of weeks of looking at this (!), I'm really thinking that it's #2.
I know this is the Richfaces forum, so I posted here because I'm seeing the problem manifest itself in my use of Richfaces. I could imagine that this post might be better suited to the JBoss AS forum (or one that covers the javax.faces.component/javax.faces.webapp classes), but I'm hoping that somebody here might point me in the right direction.
I'm actually quite surprised that I can't find a recent JIRA on this (or any other similar problems in the forums/google), so I must admit that I am very perplexed. Should I create a new JIRA, and if so, under what project? I have an ear that demonstrates this problem quite clearly.
Hopefully somebody out there can enlighten me... it would be much appreciated!
Of course, the obligatory (seam-gen) files follow.
table.xhtml, the dataTable page included in home.xhtml and user.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich" xmlns:s="http://jboss.com/products/seam/taglib"> <h:form id="navUserListForm"> <h:panelGrid columns="2" columnClasses="top" id="userPanelGrid"> <rich:dataTable value="#{userManager.userList}" var="user" id="navUserListTable" binding="#{userTableBinder.table}" rows="4" width="100%" columnClasses="top"> <rich:column sortBy="#{user.firstName}" id="firstNameCol"> <f:facet name="header">First Name</f:facet> <h:outputText value="#{user.firstName}" id="firstName" /> </rich:column> <rich:column sortBy="#{user.lastName}" id="lastNameCol"> <f:facet name="header">Last Name</f:facet> <h:outputText value="#{user.lastName}" id="lastName" /> </rich:column> <f:facet name="footer" > <rich:datascroller id="navUserListPaginator" maxPages="10" ajaxSingle="true" renderIfSinglePage="false" /> </f:facet> </rich:dataTable> </h:panelGrid> </h:form> </html>
UserTableBinder.java, used to bind the dataTable:
package com.test.faces.data; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.richfaces.component.UIDataTable; @Scope(ScopeType.SESSION) @Name("userTableBinder") public class UserTableBinder implements java.io.Serializable { private static final long serialVersionUID = 9119380620478682684L; private UIDataTable table; public UserTableBinder() { } public UIDataTable getTable() { return table; } public void setTable(UIDataTable table) { this.table = table; } }
web.xml:
<?xml version="1.0"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>test</display-name> <description>Test Application</description> <!-- Duplicate ID Bug? [RF-2218] --> <context-param> <param-name>org.ajax4jsf.SERIALIZE_SERVER_STATE</param-name> <param-value>true</param-value> </context-param> <!-- RichFaces --> <context-param> <param-name>facelets.DEVELOPMENT</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>facelets.SKIP_COMMENTS</param-name> <param-value>true</param-value> </context-param> <!-- Application Context Parameters --> <context-param> <param-name>entityManagerFactory</param-name> <param-value>java:/EntityManagerFactory/em</param-value> </context-param> <!-- JSF --> <context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xhtml</param-value> </context-param> <!-- Seam --> <listener> <listener-class>org.jboss.seam.servlet.SeamListener</listener-class> </listener> <filter> <filter-name>Seam Filter</filter-name> <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class> </filter> <filter-mapping> <filter-name>Seam Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>Seam Resource Servlet</servlet-name> <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class> </servlet> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Seam Resource Servlet</servlet-name> <url-pattern>/seam/resource/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.seam</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <security-constraint> <display-name>Restrict raw XHTML Documents</display-name> <web-resource-collection> <web-resource-name>XHTML</web-resource-name> <url-pattern>*.xhtml</url-pattern> </web-resource-collection> <auth-constraint/> </security-constraint> <login-config> <auth-method>BASIC</auth-method> </login-config> </web-app>
components.xml:
<?xml version="1.0" encoding="UTF-8"?> <components xmlns="http://jboss.com/products/seam/components" xmlns:core="http://jboss.com/products/seam/core" xmlns:persistence="http://jboss.com/products/seam/persistence" xmlns:drools="http://jboss.com/products/seam/drools" xmlns:bpm="http://jboss.com/products/seam/bpm" xmlns:security="http://jboss.com/products/seam/security" xmlns:mail="http://jboss.com/products/seam/mail" xmlns:ui="http://jboss.com/products/seam/ui" xmlns:web="http://jboss.com/products/seam/web" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:international="http://jboss.com/products/seam/international" xsi:schemaLocation= "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.1.xsd http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.1.xsd http://jboss.com/products/seam/drools http://jboss.com/products/seam/drools-2.1.xsd http://jboss.com/products/seam/bpm http://jboss.com/products/seam/bpm-2.1.xsd http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.1.xsd http://jboss.com/products/seam/mail http://jboss.com/products/seam/mail-2.1.xsd http://jboss.com/products/seam/web http://jboss.com/products/seam/web-2.1.xsd http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.1.xsd http://jboss.com/products/seam/international http://jboss.com/products/seam/international-2.1.xsd"> <core:init debug="true" jndi-pattern="@jndiPattern@"/> <core:manager concurrent-request-timeout="500" conversation-timeout="120000" conversation-id-parameter="cid" parent-conversation-id-parameter="pid"/> <web:hot-deploy-filter url-pattern="*.seam"/> <persistence:managed-persistence-context name="entityManager" auto-create="true" persistence-unit-jndi-name="java:/EntityManagerFactory/em"/> </components>