javaserverfaces
  1. javaserverfaces
  2. JAVASERVERFACES-2769

Inconsistend state Issue with a template including twice

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Invalid
    • Affects Version/s: 2.1.19
    • Fix Version/s: None
    • Component/s: facelets, state saving
    • Labels:
      None

      Description

      I meet the following issue with Mojarra 2.1.19.

      A page includes the same template twice but with different params. User can hide/show template with a button :

       
          <h:form>
              <h:commandButton action="#{sessionBean.switch1}" value="switch panel 1">
                  <f:ajax render=":panel"/>
              </h:commandButton>
              <h:commandButton action="#{sessionBean.switch2}" value="switch panel 2">
                  <f:ajax render=":panel"/>
              </h:commandButton>
          </h:form>
      
      
          <h:panelGroup id="panel">
              <c:if test="#{sessionBean.render1}">
                  <f:subview id="f1">
                      <ui:include src="form.xhtml">
                          <ui:param name="comp" value="#{rb1}"/>
                      </ui:include>
                  </f:subview>
              </c:if>
              <c:if test="#{sessionBean.render2}">
                  <f:subview id="f2">
                      <ui:include src="form.xhtml">
                          <ui:param name="comp" value="#{rb2}"/>
                      </ui:include>
                  </f:subview>
              </c:if>
          </h:panelGroup>
      

      rb1 and rb2 are two bean with scope request.
      form.xhtml contains a form with a binding :

       
          <f:subview id="#{comp.name}">
              <h:form id="myForm" binding="#{comp.binding}">
      
                  <h:outputText value="#{comp.name}" id="output"/>
              </h:form>
          </f:subview>
      

      When user clicks on the "switch panel 1", JSF throws a duplicate id exception. If I remove the binding there is no error. If I duplicate the included template there is no error.

      I reproduce the issue even if the template is included twice in different nested templates.

        Activity

        Hide
        Manfred Riem added a comment -

        Taken from the JSF specification, section 3.1.5

        "If application developers place managed beans that are pointed at by component
        binding expressions in any scope other than request scope, the system cannot
        behave correctly. This is because placing it in a scope wider than request
        scope would require thread safety, since UIComponent instances depend on
        running inside of a single thread."

        Note the snippet comes from the 2.2 specification where the wording has been
        enforced/updated to make application developers aware bindings should only be
        used with request scoped beans.

        I have verified that changing the SessionScoped to a RequestScoped makes it work.
        So I am closing this issue as Invalid.

        Show
        Manfred Riem added a comment - Taken from the JSF specification, section 3.1.5 "If application developers place managed beans that are pointed at by component binding expressions in any scope other than request scope, the system cannot behave correctly. This is because placing it in a scope wider than request scope would require thread safety, since UIComponent instances depend on running inside of a single thread." Note the snippet comes from the 2.2 specification where the wording has been enforced/updated to make application developers aware bindings should only be used with request scoped beans. I have verified that changing the SessionScoped to a RequestScoped makes it work. So I am closing this issue as Invalid.
        Hide
        nithril added a comment -

        As a workaround I have create a request bean to hold binding :

        @ManagedBean(name = "bindingHolder")
        @RequestScoped
        public class ComponentsBean {
        
            private Map<String,UIComponent> bindings = new HashMap();
        
            public Map<String, UIComponent> getBindings() {
                return bindings;
            }
        
            public void setBindings(Map<String, UIComponent> bindings) {
                this.bindings = bindings;
            }
        }
        

        On facelet (form.xhtml)

        <h:form id="myForm" binding="#{bindingHolder.bindings[comp.name]}">
           <h:outputText value="#{comp.name}" id="output"/>
        </h:form>
        

        Is this correct according to the spec?

        Show
        nithril added a comment - As a workaround I have create a request bean to hold binding : @ManagedBean(name = "bindingHolder" ) @RequestScoped public class ComponentsBean { private Map< String ,UIComponent> bindings = new HashMap(); public Map< String , UIComponent> getBindings() { return bindings; } public void setBindings(Map< String , UIComponent> bindings) { this .bindings = bindings; } } On facelet (form.xhtml) <h:form id= "myForm" binding= "#{bindingHolder.bindings[comp.name]}" > <h:outputText value= "#{comp.name}" id= "output" /> </h:form> Is this correct according to the spec?
        Hide
        Manfred Riem added a comment -

        All you need to do is to change your previous example to do @RequestScoped instead of @SessionScoped and then it works

        Show
        Manfred Riem added a comment - All you need to do is to change your previous example to do @RequestScoped instead of @SessionScoped and then it works
        Hide
        nithril added a comment -

        I cannot. SessionScoped is here at purpose to manage a single page application with nested components. A request scope will re compute all the tree on each request.

        Is I'm correct? Is my previous example this correct according to the spec?

        Show
        nithril added a comment - I cannot. SessionScoped is here at purpose to manage a single page application with nested components. A request scope will re compute all the tree on each request. Is I'm correct? Is my previous example this correct according to the spec?
        Hide
        Manfred Riem added a comment -

        It looks OK. But it works just fine with the other bean just as well. Just rename that one and stick it in @RequestScoped and then create another @SessionScoped bean for whatever you need to do in it.

        Show
        Manfred Riem added a comment - It looks OK. But it works just fine with the other bean just as well. Just rename that one and stick it in @RequestScoped and then create another @SessionScoped bean for whatever you need to do in it.

          People

          • Assignee:
            Manfred Riem
            Reporter:
            nithril
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: