eclipse-ee4j / mojarra

Mojarra, a Jakarta Faces implementation
Other
159 stars 109 forks source link

Nesting composite components results in wrong client ids #5214

Closed mkomko closed 10 months ago

mkomko commented 1 year ago

Describe the bug

A new variant of issue https://github.com/eclipse-ee4j/mojarra/issues/5023 has appeared. I first reported it to PrimeFaces under https://github.com/primefaces/primefaces/issues/9807, but it appears to be a Mojarra bug (4.0.1).

An AJAX event cannot update the components correctly because of wrong client ids. I lack the technical knowledge to explain the problem in more detail, I'm sure @tandraschko could help out.

The problem appears under the following conditions:

I suspected it was related to p:autoUpdate, but according to the PrimeFaces devs everything seems correct on their side and has to be fixed in Mojarra.

To Reproduce

Steps to reproduce the behavior:

  1. Clone the reproducer from https://github.com/mkomko/primefaces-test/tree/dialog-ajax-update-issue
  2. Run the reproducer using mvn clean jetty:run -P mojarra40
  3. Browse to http://localhost:8080/primefaces-test/
  4. Click the "Open Dialog" button
  5. Select another item from the drop-down menu
  6. See that the value is reset by the AJAX update
  7. Also see, that the setter wasn't even called (the output wasn't printed in the console) and so the value wasn't processed

Expected behavior

The setter is called, the value is processed and rendered back to the client.

Additional context

Excerpt of the view:

<h:form id="frmTest">
    <p:commandButton id="openTestDialog"
                     value="Open Dialog"
                     action="#{testView.openTestDialog}"
                     update="testDialog"/>
</h:form>

<test:dialogTest id="testDialog"/>

Excerpt of the dialog composite component:

<div id="#{cc.clientId}">

    <test:dialogBase id="dialog"
                     header="Test Dialog"
                     visible="#{testDialogAction.visible}">

        <test:selectItem value="#{testDialogAction.selectedItem}"
                         selectItems="#{testDialogAction.items}"
                         updateOnChange="#{cc.clientId}"/>

    </test:dialogBase>

</div>

Excerpt of the base dialog composite component:

<h:form id="dialogForm">

   <p:dialog id="dialog"
             visible="#{cc.attrs.visible}">

      <f:facet name="header">
            <h1>#{cc.attrs.header}</h1>
      </f:facet>

      <cc:insertChildren/>

   </p:dialog>

</h:form>

Excerpt of the drop-down composite component:

<div id="#{cc.clientId}">
    <p:selectOneMenu id="items"
                     converter="omnifaces.SelectItemsIndexConverter"
                     value="#{cc.attrs.value}">
        <f:selectItems value="#{cc.attrs.selectItems}"
                       var="i"
                       itemLabel="#{i.name}"/>
        <p:ajax event="change"
                update="#{cc.attrs.updateOnChange}"/>
    </p:selectOneMenu>

    <p:messages>
        <p:autoUpdate/>
    </p:messages>
</div>

Excerpt of the dialog action bean:

public Item getSelectedItem() {
    return selectedItem;
}

public void setSelectedItem(Item selectedItem) {
    System.out.println("Setter called");
    this.selectedItem = selectedItem;
}
BalusC commented 1 year ago

Duplicates https://github.com/eclipse-ee4j/mojarra/issues/4696. It's caused by f:facet.

For reference, MyFaces marked this issue as WONTFIX: https://issues.apache.org/jira/browse/MYFACES-4161

Leaving ticket open because we probably need to explain/mention it somewhere in the spec.

mkomko commented 1 year ago

@BalusC Are you sure it's the same issue? In our case the problem does not seem to be related to f:facet, unless it's somehow used internally. I removed the only facet in the reproducer (a dialog header) and the issue still occurs. I updated the reproducer linked above.

Also, we migrated our application from Mojarra to MyFaces due to this problem. We don't face the issue there. You can confirm that when you run the (updated) reproducer using mvn clean jetty:run -P myfaces40

melloware commented 11 months ago

@BalusC we have another instance of this being reported and it also has a working reproducer: https://github.com/primefaces/primefaces/issues/10552

At least it looks a lot like this issue where the InputText inside a CC is not being marked as invalid.

It is Mojarra 4.0.3

melloware commented 11 months ago

Reproducer: pf-10552.zip

mvn clean jetty:run -Pmojarra40 FAILS! mvn clean jetty:run -Pmyfaces40 WORKS

It works in plain dialog but do the same in a composite component and the Input is not marked for validation.

BalusC commented 11 months ago

Reproduced.

BalusC commented 11 months ago

Please retry with 4.0.5-SNAPSHOT.

This is by the way a regression of https://github.com/eclipse-ee4j/mojarra/pull/4808 because this all worked in Mojarra 2.3.16 (but which was most probably done way much more inefficient). See also first half of this comment https://github.com/eclipse-ee4j/mojarra/issues/5065#issuecomment-1073039521 for an in depth explanation (until the part "... explains the observable problems").

melloware commented 11 months ago

Thanks @BalusC i will test out!

melloware commented 11 months ago

I can confirm our use cases are fixed in 4.0.5-SNAPSHOT!

mkomko commented 10 months ago

@BalusC I would like to test it out as well, but I can't find information about the snapshot repository anywhere. Where can I find it? Thanks in advance!

melloware commented 10 months ago

@mkomko I just checked out the 4.0 branch here and ran mvn clean install

mkomko commented 10 months ago

@melloware Thank you. @BalusC I now tested our use case and it's not fixed. But I also noticed that the commit referenced above (https://github.com/eclipse-ee4j/mojarra/commit/1f272e5e6842f21137a37a7730fef0f2889ec160) is not currently in the 4.0 branch?

mkomko commented 10 months ago

@BalusC I now tested using the _mojarra_issue5214 branch and our use case works!

mnriem commented 10 months ago

@BalusC Is this one now completed and can it be closed out?

BalusC commented 10 months ago

No, the associated PR has not been merged.

BalusC commented 10 months ago

It has been merged now.

mkomko commented 8 months ago

@BalusC Using Mojarra 4.0.5 we still get the following exception under specific (yet unknown) circumstances:

Caused by: org.primefaces.expression.ComponentNotFoundException: Cannot find component for expression "myDialog:dialog:dialogForm:myDialogPanel" referenced from "myDialog:dialog:searchCommand".
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.expression.SearchExpressionFacade.cannotFindComponent(SearchExpressionFacade.java:729)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.expression.SearchExpressionFacade.resolveClientIds(SearchExpressionFacade.java:263)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.util.AjaxRequestBuilder.addExpressions(AjaxRequestBuilder.java:159)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.util.AjaxRequestBuilder.update(AjaxRequestBuilder.java:152)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.renderkit.CoreRenderer.preConfiguredAjaxRequestBuilder(CoreRenderer.java:463)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.renderkit.CoreRenderer.preConfiguredAjaxRequestBuilder(CoreRenderer.java:452)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.component.remotecommand.RemoteCommandRenderer.encodeEnd(RemoteCommandRenderer.java:68)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:585)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:85)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:67)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.component.panel.PanelRenderer.encodeContent(PanelRenderer.java:249)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.component.panel.PanelRenderer.encodeMarkup(PanelRenderer.java:150)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.component.panel.PanelRenderer.encodeEnd(PanelRenderer.java:77)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:585)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:85)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:67)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.component.dialog.DialogRenderer.encodeContent(DialogRenderer.java:203)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.component.dialog.DialogRenderer.encodeMarkup(DialogRenderer.java:126)
    at deployment.ourapp.ear.ourapp-web.war//org.primefaces.component.dialog.DialogRenderer.encodeEnd(DialogRenderer.java:55)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:585)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponent.encodeAll(UIComponent.java:1442)
    at jakarta.faces.impl@4.0.5//jakarta.faces.render.Renderer.encodeChildren(Renderer.java:146)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:556)
    at jakarta.faces.impl@4.0.5//com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:257)
    at jakarta.faces.impl@4.0.5//com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:82)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:556)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponent.encodeAll(UIComponent.java:1435)
    at jakarta.faces.impl@4.0.5//com.sun.faces.renderkit.html_basic.CompositeRenderer.encodeChildren(CompositeRenderer.java:50)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:556)
    at jakarta.faces.impl@4.0.5//com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:257)
    at jakarta.faces.impl@4.0.5//com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:82)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:556)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponent.encodeAll(UIComponent.java:1435)
    at jakarta.faces.impl@4.0.5//com.sun.faces.renderkit.html_basic.CompositeRenderer.encodeChildren(CompositeRenderer.java:50)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:556)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponent.encodeAll(UIComponent.java:1435)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponent.encodeAll(UIComponent.java:1438)
    at jakarta.faces.impl@4.0.5//jakarta.faces.component.UIComponent.encodeAll(UIComponent.java:1438)
    at jakarta.faces.impl@4.0.5//com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:449)
    at jakarta.faces.impl@4.0.5//com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:163)
    at jakarta.faces.impl@4.0.5//jakarta.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:125)
    at jakarta.faces.impl@4.0.5//jakarta.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:125)
    at jakarta.faces.impl@4.0.5//jakarta.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:125)
    at deployment.ourapp.ear.ourapp-web.war//org.omnifaces.viewhandler.OmniViewHandler.renderView(OmniViewHandler.java:166)
    at jakarta.faces.impl@4.0.5//jakarta.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:125)
    at jakarta.faces.impl@4.0.5//jakarta.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:125)
    at jakarta.faces.impl@4.0.5//com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:93)
    at jakarta.faces.impl@4.0.5//com.sun.faces.lifecycle.Phase.doPhase(Phase.java:72)
    at jakarta.faces.impl@4.0.5//com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:150)
    at jakarta.faces.impl@4.0.5//jakarta.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:692)
    ... 83 more

Please note, that both components (the one that cannot be found and the one that it is referenced from) are in the same naming container myDialog:dialog:dialogForm. Do you anything that could still cause this? A slightly different case maybe?

mkomko commented 8 months ago

It turns out it was custom code of ours where we programmatically edited the facets of a DataTable column? No idea how it causes this, but maybe we'll find a different solution...