ICEfaces
  1. ICEfaces
  2. ICE-7702

Use of the f:ajax tag in h:selectMany[Checkbox, Listbox] within 2+ naming containers throws an exception

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Invalid
    • Affects Version/s: 3.0
    • Fix Version/s: 3.1
    • Component/s: Framework, ICE-Components
    • Labels:
      None
    • Environment:
      ICEfaces 3 ACE portal portlet Mojarra
    • Assignee Priority:
      P2
    • Affects:
      Documentation (User Guide, Ref. Guide, etc.), Compatibility/Configuration
    • Workaround Exists:
      Yes
    • Workaround Description:
      Hide
      Do not use f:ajax tag with Mojarra, or use MyFaces

      Instead of using f:ajax, manually add an onclick handler and make it call the submit function yourself

      After this jira's commits, use the ace:ajax tag instead of f:ajax
      Show
      Do not use f:ajax tag with Mojarra, or use MyFaces Instead of using f:ajax, manually add an onclick handler and make it call the submit function yourself After this jira's commits, use the ace:ajax tag instead of f:ajax

      Description

      When trying to add the plain ace:tabset example as a portlet to a portal page, the following exception is thrown:

      javax.faces.FacesException: <f:ajax> contains an unknown id 'A4076:j_idt449:_t451' - cannot locate it in the context of the component _t451
      at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.getResolvedId(AjaxBehaviorRenderer.java:285)
      at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.appendIds(AjaxBehaviorRenderer.java:272)
      at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.buildAjaxCommand(AjaxBehaviorRenderer.java:212)
      at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.getScript(AjaxBehaviorRenderer.java:86)
      at javax.faces.component.behavior.ClientBehaviorBase.getScript(ClientBehaviorBase.java:103)
      at com.sun.faces.renderkit.RenderKitUtils.getSingleBehaviorHandler(RenderKitUtils.java:1610)
      at com.sun.faces.renderkit.RenderKitUtils.renderHandler(RenderKitUtils.java:1703)
      at com.sun.faces.renderkit.RenderKitUtils.renderSelectOnclick(RenderKitUtils.java:421)
      at com.sun.faces.renderkit.html_basic.SelectManyCheckboxListRenderer.renderOption(SelectManyCheckboxListRenderer.java:361)
      at com.sun.faces.renderkit.html_basic.SelectManyCheckboxListRenderer.encodeEnd(SelectManyCheckboxListRenderer.java:180)
      at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875)
      at org.icefaces.ace.util.Utils.renderChild(Utils.java:61)
      at org.icefaces.ace.util.Utils.renderChildren(Utils.java:43)
      at org.icefaces.ace.util.Utils.renderChild(Utils.java:59)
      at org.icefaces.ace.component.tabset.TabSetRenderer.renderTabBody(TabSetRenderer.java:431)
      at org.icefaces.ace.component.tabset.TabSetRenderer.doTab(TabSetRenderer.java:512)
      at org.icefaces.ace.component.tabset.TabSetRenderer.doTabs(TabSetRenderer.java:452)
      at org.icefaces.ace.component.tabset.TabSetRenderer.recursivelyRenderSafe(TabSetRenderer.java:323)
      at org.icefaces.ace.component.tabset.TabSetRenderer.encodeEnd(TabSetRenderer.java:261)
      at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875)
      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1764)
      at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
      at org.icefaces.impl.renderkit.RendererWrapper.encodeChildren(RendererWrapper.java:49)
      at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
      at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:304)
      at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:105)
      at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
      at org.icefaces.ace.renderkit.CoreRenderer.renderChild(CoreRenderer.java:72)
      at org.icefaces.ace.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:60)
      at org.icefaces.ace.component.panel.PanelRenderer.encodeContent(PanelRenderer.java:208)
      at org.icefaces.ace.component.panel.PanelRenderer.encodeMarkup(PanelRenderer.java:131)
      at org.icefaces.ace.component.panel.PanelRenderer.encodeEnd(PanelRenderer.java:71)
      at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875)
      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1764)
      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1760)
      at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1760)
      at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:401)
      at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
      at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
      at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
      at org.portletfaces.bridge.BridgeImpl.doFacesRequest(BridgeImpl.java:433)


      Remove the f:ajax tag from the following markup allows the tabset to work normally so the issue is not the tabset component itself but the use of the f:ajax tag in the body of the tab pane:

                  <ace:tabSet id="sampleTabSet" clientSide="false">
                      <ace:tabPane label="To Do List">
                          <h:selectManyCheckbox layout="pageDirection" selectedClass="selectedCheckBox">
                                      <f:selectItems value="#{tabSet.toDoList}"
                                                          var="listItem"
                                                          itemValue="#{listItem.value}"
                                                          itemLabel="#{listItem.key}"/>
       //Remove -> <f:ajax execute="@this" render="sampleTabSet"/>
                          </h:selectManyCheckbox>
                      </ace:tabPane>

        Issue Links

          Activity

          Hide
          Deryk Sinotte added a comment -

          In the ace:accordionPanel example, we use a different technique - adding an onchange handler instead - and this doesn't have a problem:

          <ace:accordion collapsible="true">
          <ace:accordionPane title="My To Do List">
          <h:selectManyCheckbox layout="pageDirection" selectedClass="selectedCheckBox" onchange="submit();">
          <f:selectItems value="#

          {accordionPanelBean.toDoList}

          "
          var="listItem"
          itemValue="#

          {listItem.value}

          "
          itemLabel="#

          {listItem.key}

          "/>
          </h:selectManyCheckbox>
          </ace:accordionPane>

          Using the same technique (and removing the f:ajax tag) in ace:tabSet also works.

          Show
          Deryk Sinotte added a comment - In the ace:accordionPanel example, we use a different technique - adding an onchange handler instead - and this doesn't have a problem: <ace:accordion collapsible="true"> <ace:accordionPane title="My To Do List"> <h:selectManyCheckbox layout="pageDirection" selectedClass="selectedCheckBox" onchange="submit();"> <f:selectItems value="# {accordionPanelBean.toDoList} " var="listItem" itemValue="# {listItem.value} " itemLabel="# {listItem.key} "/> </h:selectManyCheckbox> </ace:accordionPane> Using the same technique (and removing the f:ajax tag) in ace:tabSet also works.
          Hide
          Deryk Sinotte added a comment -

          To narrow it down further, this is only a problem with Mojarra. With MyFaces, the use of f:ajax works fine. I've updated the environment information and the workaround to reflect this.

          At this point, I can only speculate that there is a difference in the findComponent algorithm that accounts for this difference.

          Show
          Deryk Sinotte added a comment - To narrow it down further, this is only a problem with Mojarra. With MyFaces, the use of f:ajax works fine. I've updated the environment information and the workaround to reflect this. At this point, I can only speculate that there is a difference in the findComponent algorithm that accounts for this difference.
          Hide
          Deryk Sinotte added a comment -

          I've removed the f:ajax from the tabset.xhtml file and added the onchange="submit();" mechanism that we using in the accordion panel for the time being so that specific showcase demo works when running under Mojarra on Liferay.

          Show
          Deryk Sinotte added a comment - I've removed the f:ajax from the tabset.xhtml file and added the onchange="submit();" mechanism that we using in the accordion panel for the time being so that specific showcase demo works when running under Mojarra on Liferay.
          Hide
          Ted Goddard added a comment -

          It's possible that MyFaces is sending "@this" to the client to be resolved at submit time while mojarra is attempting to resolve "@this" server-side. It should be possible to determine if these are the strategies by looking at the network traffic.

          Show
          Ted Goddard added a comment - It's possible that MyFaces is sending "@this" to the client to be resolved at submit time while mojarra is attempting to resolve "@this" server-side. It should be possible to determine if these are the strategies by looking at the network traffic.
          Hide
          Mark Collette added a comment -

          From the code at the top of the stack, and the exception message, the problem is that some code has already converted @this to a clientId, and the clientId doesn't start with a colon, so it's being used as a relative findComponent String from the selectManyCheckbox, and so is failing the search.

          Show
          Mark Collette added a comment - From the code at the top of the stack, and the exception message, the problem is that some code has already converted @this to a clientId, and the clientId doesn't start with a colon, so it's being used as a relative findComponent String from the selectManyCheckbox, and so is failing the search.
          Hide
          Mark Collette added a comment -

          From Mojarra's AjaxBehaviorRenderer:

          StringBuilder ajaxCommand = new StringBuilder(256);
          Collection<String> execute = ajaxBehavior.getExecute();
          Collection<String> render = ajaxBehavior.getRender();
          String onevent = ajaxBehavior.getOnevent();
          String onerror = ajaxBehavior.getOnerror();
          String sourceId = behaviorContext.getSourceId();
          Collection<ClientBehaviorContext.Parameter> params = behaviorContext.getParameters();

          // Needed workaround for SelectManyCheckbox - if execute doesn't have sourceId,
          // we need to add it - otherwise, we use the default, which is sourceId:child, which
          // won't work.
          ClientBehaviorContext.Parameter foundparam = null;
          for (ClientBehaviorContext.Parameter param : params) {
          if (param.getName().equals("incExec") && (Boolean)param.getValue())

          { foundparam = param; }

          }
          if (foundparam != null && !execute.contains(sourceId))

          { execute = new LinkedList<String>(execute); execute.add(component.getClientId()); <<< This is what breaks it }
          Show
          Mark Collette added a comment - From Mojarra's AjaxBehaviorRenderer: StringBuilder ajaxCommand = new StringBuilder(256); Collection<String> execute = ajaxBehavior.getExecute(); Collection<String> render = ajaxBehavior.getRender(); String onevent = ajaxBehavior.getOnevent(); String onerror = ajaxBehavior.getOnerror(); String sourceId = behaviorContext.getSourceId(); Collection<ClientBehaviorContext.Parameter> params = behaviorContext.getParameters(); // Needed workaround for SelectManyCheckbox - if execute doesn't have sourceId, // we need to add it - otherwise, we use the default, which is sourceId:child, which // won't work. ClientBehaviorContext.Parameter foundparam = null; for (ClientBehaviorContext.Parameter param : params) { if (param.getName().equals("incExec") && (Boolean)param.getValue()) { foundparam = param; } } if (foundparam != null && !execute.contains(sourceId)) { execute = new LinkedList<String>(execute); execute.add(component.getClientId()); <<< This is what breaks it }
          Hide
          Mark Collette added a comment -

          com.sun.faces.renderkit.html_basic.SelectManyCheckboxListRenderer.renderOption(
          FacesContext context,
          UIComponent component,
          Converter converter,
          SelectItem curItem,
          Object currentSelections,
          Object[] submittedValues,
          boolean alignVertical,
          int itemNumber,
          OptionComponentInfo optionInfo)
          at line 361 calls: RenderKitUtils.renderSelectOnclick(context, component, true); which adds the specific param that AjaxBehaviorRenderer is looking for.

          So it looks like it comes down to if sourceId is specified, and is in the execute list. At this point, execute should consist of "@this".

          Show
          Mark Collette added a comment - com.sun.faces.renderkit.html_basic.SelectManyCheckboxListRenderer.renderOption( FacesContext context, UIComponent component, Converter converter, SelectItem curItem, Object currentSelections, Object[] submittedValues, boolean alignVertical, int itemNumber, OptionComponentInfo optionInfo) at line 361 calls: RenderKitUtils.renderSelectOnclick(context, component, true); which adds the specific param that AjaxBehaviorRenderer is looking for. So it looks like it comes down to if sourceId is specified, and is in the execute list. At this point, execute should consist of "@this".
          Hide
          Mark Collette added a comment -

          The Mojarra jira for the issue:

          http://java.net/jira/browse/JAVASERVERFACES-1579

          Show
          Mark Collette added a comment - The Mojarra jira for the issue: http://java.net/jira/browse/JAVASERVERFACES-1579
          Hide
          Mark Collette added a comment -

          Only h:selectManyCheckbox and h:selectManyListbox exhibit this problem, where if they are within 2+ levels of naming containers, and have an f:ajax tag, and are using Mojarra, that it will throw an excdption. It doesn't require portlets, but portlets will always fail since the portlet UIViewRoot is a naming container, and the selectMany* component need to be in a form, so you're already two levels deep. But you could just as well have a form and a dataTable or f:subview.

          It doesn't matter what you specify to execute, because the mojarra code will add a bogus entry to the execute list.

          Show
          Mark Collette added a comment - Only h:selectManyCheckbox and h:selectManyListbox exhibit this problem, where if they are within 2+ levels of naming containers, and have an f:ajax tag, and are using Mojarra, that it will throw an excdption. It doesn't require portlets, but portlets will always fail since the portlet UIViewRoot is a naming container, and the selectMany* component need to be in a form, so you're already two levels deep. But you could just as well have a form and a dataTable or f:subview. It doesn't matter what you specify to execute, because the mojarra code will add a bogus entry to the execute list.
          Hide
          Mark Collette added a comment -

          Modified the ace:ajax rendering code to handle differences between ACE components, and regular h: components, so that it can also be used with h: components. So far only verified with the h:selectManyCheckbox from the test scenario.

          This code varies noticeably between trunk and branch, so branch will require separate implementation and verification.

          <f:subview id="testSub">
          <h:form id="form">
          <ace:tabSet id="sampleTabSet" clientSide="false">
          <ace:tabPane id="toDoList" label="To Do List">
          <h:selectManyCheckbox id="list" layout="pageDirection" selectedClass="selectedCheckBox">
          <f:selectItems value="#

          {tabSet.toDoList}

          "
          var="listItem"
          itemValue="#

          {listItem.value}

          "
          itemLabel="#

          {listItem.key}

          "/>
          <ace:ajax execute="@this" render="sampleTabSet"/>
          </h:selectManyCheckbox>

          trunk
          Subversion 28310

          Show
          Mark Collette added a comment - Modified the ace:ajax rendering code to handle differences between ACE components, and regular h: components, so that it can also be used with h: components. So far only verified with the h:selectManyCheckbox from the test scenario. This code varies noticeably between trunk and branch, so branch will require separate implementation and verification. <f:subview id="testSub"> <h:form id="form"> <ace:tabSet id="sampleTabSet" clientSide="false"> <ace:tabPane id="toDoList" label="To Do List"> <h:selectManyCheckbox id="list" layout="pageDirection" selectedClass="selectedCheckBox"> <f:selectItems value="# {tabSet.toDoList} " var="listItem" itemValue="# {listItem.value} " itemLabel="# {listItem.key} "/> <ace:ajax execute="@this" render="sampleTabSet"/> </h:selectManyCheckbox> trunk Subversion 28310
          Hide
          Mark Collette added a comment -

          Since there's no real fix for this issue, aside from Mojarra fixing it, or using work-arounds, then we'll link to ICE-7909, which is a jira for making ace:ajax work with h: components, so that it can be used instead of f:ajax.

          Show
          Mark Collette added a comment - Since there's no real fix for this issue, aside from Mojarra fixing it, or using work-arounds, then we'll link to ICE-7909 , which is a jira for making ace:ajax work with h: components, so that it can be used instead of f:ajax.
          Hide
          Mark Collette added a comment -

          Subversion 28310 should have been made under ICE-7909.

          Show
          Mark Collette added a comment - Subversion 28310 should have been made under ICE-7909 .

            People

            • Assignee:
              Mark Collette
              Reporter:
              Deryk Sinotte
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: