welcome examples jsf jsf-2 primefaces

examples - La identificación del componente PrimeFaces/JSF no se encuentra dentro de p: datatable



templates jsf primefaces (1)

Estoy empezando con PrimeFaces 3.3.1 que viene de RichFaces 3 y 4.

Tengo una tabla de datos con la estructura:

<f:facet name="header"> <h:outputText value="Employees" /> </f:facet> <p:column sortBy="#{emp.lastName}"> <f:facet name="header"> <h:outputText value="Last Name" /> </f:facet> <h:outputText value="#{emp.lastName}" /> </p:column> <p:column> <f:facet name="header"> <h:outputText value="First Name" /> </f:facet> <h:outputText value="#{emp.firstName}" /> </p:column> ... <p:column> <p:commandButton icon="ui-icon ui-icon-trash" value="Remove" process="@this" update="employee-remove-dialog" oncomplete="employeeRemoveDialog.show();"> <f:setPropertyActionListener target="#{employeeManager.currentEmployee}" value="#{emp}" /> </p:commandButton> </p:column> </p:dataTable> <p:dialog header="Remove Employee" modal="true" appendToBody="true" widgetVar="employeeRemoveDialog" id="employee-remove-dialog"> <h:outputText value="Remove employee #{employeeManager.currentEmployee.fullName}?" /> <f:facet name="footer"> <p:commandButton icon="ui-icon ui-icon-check" value="OK" action="#{employeeManager.deleteEmployee}" process="@this" update="employee-list" oncomplete="employeeRemoveDialog.hide();" /> <p:commandButton icon="ui-icon ui-icon-close" value="Cancel" onclick="employeeRemoveDialog.hide();" ajax="false" immediate="true" /> </f:facet> </p:dialog> </h:form>

Sin embargo, PrimeFaces lanza una excepción:

09:36:08,961 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (http-localhost-127.0.0.1-8080-1) Error Rendering View[/employeeList.xhtml]: javax.faces.FacesException: Cannot find component with identifier "employee-remove-dialog" referenced from "j_idt30:employee-list:0:j_idt41". at org.primefaces.util.ComponentUtils.findClientIds(ComponentUtils.java:251) [primefaces-3.3.1.jar:] at org.primefaces.util.AjaxRequestBuilder.addIds(AjaxRequestBuilder.java:102) [primefaces-3.3.1.jar:] at org.primefaces.util.AjaxRequestBuilder.update(AjaxRequestBuilder.java:90) [primefaces-3.3.1.jar:] at org.primefaces.renderkit.CoreRenderer.buildAjaxRequest(CoreRenderer.java:195) [primefaces-3.3.1.jar:] at org.primefaces.component.commandbutton.CommandButtonRenderer.encodeMarkup(CommandButtonRenderer.java:74) [primefaces-3.3.1.jar:] at org.primefaces.component.commandbutton.CommandButtonRenderer.encodeEnd(CommandButtonRenderer.java:49) [primefaces-3.3.1.jar:] at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:312) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:185) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:129) [jsf-impl-2.1.7-jbossorg-2.jar:] at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1779) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at org.primefaces.component.datatable.DataTableRenderer.encodeRegularCell(DataTableRenderer.java:780) [primefaces-3.3.1.jar:] at org.primefaces.component.datatable.DataTableRenderer.encodeRow(DataTableRenderer.java:741) [primefaces-3.3.1.jar:] at org.primefaces.component.datatable.DataTableRenderer.encodeTbody(DataTableRenderer.java:645) [primefaces-3.3.1.jar:] at org.primefaces.component.datatable.DataTableRenderer.encodeRegularTable(DataTableRenderer.java:248) [primefaces-3.3.1.jar:] at org.primefaces.component.datatable.DataTableRenderer.encodeMarkup(DataTableRenderer.java:220) [primefaces-3.3.1.jar:] at org.primefaces.component.datatable.DataTableRenderer.encodeEnd(DataTableRenderer.java:107) [primefaces-3.3.1.jar:] at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1786) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.render.Renderer.encodeChildren(Renderer.java:168) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:55) [primefaces-3.3.1.jar:] at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:43) [primefaces-3.3.1.jar:] at org.primefaces.component.layout.LayoutUnitRenderer.encodeEnd(LayoutUnitRenderer.java:51) [primefaces-3.3.1.jar:] at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1786) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:402) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125) [jsf-impl-2.1.7-jbossorg-2.jar:] at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) [jsf-impl-2.1.7-jbossorg-2.jar:] at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:] at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final] at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:] at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:] at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:] at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:] at java.lang.Thread.run(Unknown Source) [rt.jar:1.7.0_04]

La identificación no se puede encontrar. Hmm ... Básicamente copié la estructura de RichFaces. Allí, el botón de la fila para eliminar o editar la fila no necesita el: employee-form: ... prefixing. Me pregunto porque.

Al asignarle un ID a la forma y al prefijar las referencias del componente PF con la sintaxis '':'', el código se ejecuta como se esperaba:

<h:form id="employee-form"> <p:dataTable ...> ... <p:column> <h:panelGrid ...> <p:commandButton ... update=":employee-form:employee-remove-dialog" ...> ... </p:commandButton> </h:panelGrid> </p:column> </p:dataTable> <p:dialog ... id="employee-remove-dialog"> </p:dialog> </h:form>

P:

¿Por qué ap: datatable necesita prefijar los ID raíz JSF? Tal vez es mi código, pero el ejemplo publicado parece mínimo para mí. En cualquier caso, usar esto dará como resultado identificaciones posiblemente largas en toda la aplicación.

¿Qué estoy haciendo mal?

PD: estoy en JBoss AS 7.1.1.Final, Mojarra 2.1.7, PF 3.3.1


PrimeFaces utiliza el algoritmo JSF estándar proporcionado por UIComponent#findComponent() para buscar componentes por una ID de cliente determinada. El algoritmo se describe en detalle en el javadoc antes mencionado. Aquí hay un extracto de relevancia:

Una expresión de búsqueda consiste en un identificador (que coincide exactamente con la propiedad id de un UIComponent , o una serie de identificadores vinculados por el valor del carácter UINamingContainer#getSeparatorChar . El algoritmo de búsqueda debe funcionar de la siguiente manera, aunque se pueden usar alogritos alternativos siempre que el resultado final sea el mismo:

  • Identifique el UIComponent que será la base para la búsqueda, deteniéndose tan pronto como se cumpla una de las siguientes condiciones:
    • Si la expresión de búsqueda comienza con el carácter separador (llamado expresión de búsqueda "absoluta"), la base será el UIComponent raíz del árbol de componentes. El carácter separador principal se eliminará y el resto de la expresión de búsqueda se tratará como una expresión de búsqueda "relativa" como se describe a continuación.
    • De lo contrario, si este UIComponent es un NamingContainer , servirá como base.
    • De lo contrario, busque los padres de este componente. Si se encuentra un NamingContainer , será la base.
    • De lo contrario (si no se encuentra NamingContainer ), el UIComponent raíz será la base.
  • La expresión de búsqueda (posiblemente modificada en el paso anterior) ahora es una expresión de búsqueda "relativa" que se utilizará para ubicar el componente (si lo hay) que tiene un ID que coincida, dentro del alcance del componente base. La coincidencia se realiza de la siguiente manera:
    • Si la expresión de búsqueda es un identificador simple, este valor se compara con la propiedad id y recursivamente a través de las facetas e hijos del UIComponent base (excepto que si se encuentra un NamingContainer descendiente, sus propias facetas e hijos no se buscan).
    • Si la expresión de búsqueda incluye más de un identificador separado por el carácter separador, el primer identificador se usa para ubicar un NamingContainer por las reglas en el punto anterior. Luego, se findComponent() método findComponent() de este NamingContainer , pasando el resto de la expresión de búsqueda.

RichFaces utiliza el mismo algoritmo "con algunas excepciones adicionales" .

"reRender" usa el algoritmo UIComponent.findComponent() (con algunas excepciones adicionales) para encontrar el componente en el árbol de componentes.

Esas excepciones adicionales no se describen en detalle en ninguna parte, pero es bien sabido que los identificadores de componentes relativos (es decir, aquellos que no comienzan con NamingContainer no solo se buscan en el contexto del NamingContainer primario más NamingContainer , sino también en todos los demás componentes de NamingContainer en la misma vista ( que es un trabajo relativamente caro por cierto).