5 Replies Latest reply on Apr 6, 2014 4:37 AM by croco

    Rich:tree reloaded when it shouldn't be

    croco

      I'm having troubles with rich:tree. In every page where is a tree, whenever an ajax call is executed it crashes and I get an duplicate component id error:

       

      11:02:30,770 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (http-/0.0.0.0:8080-4) JSF1007: Duplicate component ID bscRpPrmF:foldersTree:j_idt278 found in view.
      11:02:30,773 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (http-/0.0.0.0:8080-4) +id: j_id1
      type: javax.faces.component.UIViewRoot@41d6afee
      
      

       

      I think there is a problem with rich:tree because is reloaded even when it shouldn't be. I've created a very simple example:

       

      Tree backing bean:

      @ManagedBean
      @SessionScoped
      public class TreeBackingBean implements Serializable {
          private SimpleTreeNode<TreeObject> tree;
      
      
          @PostConstruct
          private void initBean() {
              tree = new TreeDataProvider().getTree();
          }
      
      
          // tree getter/setter
          public SimpleTreeNode<TreeObject> getTree() {
              return tree;
          }
      
      
          public void setTree(SimpleTreeNode<TreeObject> tree) {
              this.tree = tree;
          }
      }
      
      

       

      Tree data provider:

      public class TreeDataProvider {
          private SimpleTreeNode<TreeObject> root;
      
      
          public SimpleTreeNode<TreeObject> getTree() {
              if (root == null) {
                  root = new SimpleTreeNode<TreeObject>(false, null, null);
      
      
                  // node 1.1
                  SimpleTreeNode<TreeObject> child = new SimpleTreeNode<TreeObject>(false, "Node 1.1", new TreeObject("Node", "1.1"));
                  root.addChild(child.hashCode(), child);
      
      
                  // node 1.1.1
                  SimpleTreeNode<TreeObject> subChild = new SimpleTreeNode<TreeObject>(true, "Leaf 1.1.1", new TreeObject("Leaf", "1.1.1"));
                  child.addChild(subChild.hashCode(), subChild);
      
      
                  // node 1.1.2
                  subChild =  new SimpleTreeNode<TreeObject>(true, "Leaf 1.1.2", new TreeObject("Leaf", "1.1.2"));
                  child.addChild(subChild.hashCode(), subChild);
      
      
                  // node 1.2
                  child = new SimpleTreeNode<TreeObject>(true, "Leaf 1.2", new TreeObject("Leaf", "1.2"));
                  root.addChild(child.hashCode(), child);
      
      
                  // node 1.3
                  child = new SimpleTreeNode<TreeObject>(false, "Node 1.3", new TreeObject("Node", "1.3"));
                  root.addChild(child.hashCode(), child);
      
      
                  // node 1.3.1
                  subChild = new SimpleTreeNode<TreeObject>(true, "Leaf 1.3.1", new TreeObject("Leaf", "1.3.1"));
                  child.addChild(subChild.hashCode(), subChild);
              }
              return root;
          }
      }
      
      

       

      xhtml:

      <h:body>
          <h3>Rich Tree example</h3>
          <h:form>
              <rich:tree value="#{treeBackingBean.tree}" var="node" selectionType="client" toggleType="client" styleClass="tree">
                  <rich:treeNode expanded="#{node.selected}">
                      <h:outputText value="#{node.name}" />
                  </rich:treeNode>
              </rich:tree>
      
      
              <br/>
              <h:outputText id="randomNumber" value="Random number: #{helloBean.randomNumber()}" />
      
      
              <br/>
              <a4j:commandLink value="Ajax" render="@this" execute="@this" limitRender="true" />
          </h:form>
      
      
          <br/>
          <a4j:log level="debug" />
      
      
      </h:body>
      
      

       

      So the problem is that every time commandLink is clicked, treeBackingBean.getTree() is executed. As far as I understand this is wrong. I put also an random number output just to double check if anything else is executed.

       

      CommandLink's execute @this should define that only the command link itself should be processed and render @this defines that only command link is re rendered. So why getTree is executed? I think this is somehow connected with my duplicate id problem.

        • 1. Re: Rich:tree reloaded when it shouldn't be
          bleathem

          Re-rendering the tree should not result in a duplicate ID problem.  Do you see the duplicate id error in your simple reproducer?

          • 2. Re: Rich:tree reloaded when it shouldn't be
            croco

            It looks like the tree is rendered twice on the same page. I've tried a few different things and it seems that there is a problem with attribute rendered on rich:treeNode and on nodeType on rich:tree. Whenever I tried to use this two attributes it keeps crashing, without this two it looks its works fine.

             

            NodeType it's not a problem, I just put render on outputs inside the node. Not being able to use rendered is somehow a bigger problem. I have filter implemented in the tree, so that I don't have to rebuild the whole tree every time, I just put rendered to false.

            • 3. Re: Rich:tree reloaded when it shouldn't be
              bleathem

              Can you file a jira issue with a simplified reproducer?

              1 of 1 people found this helpful
              • 4. Re: Rich:tree reloaded when it shouldn't be
                croco

                Ok, I'll prepare a simple example tomorrow morning and I'll attach it to the jira request.

                • 5. Re: Rich:tree reloaded when it shouldn't be
                  croco

                  After 2 weeks of banging my head against the wall I figured out how to fix it. I just put not in the rendered attribute and obviously negated the node.rendered value.

                   

                  2 days ago I was preparing a simple project with just a tree that I promised, to reproduce the bug and it was working. Basicly it was only the tree copied from my production application where it kept crashing with the 'Duplicate component ID' problem. So I tried experimenting a bit and put 'not' in front of the condition and it started working.

                   

                  Here is my actual production code:

                  <rich:tree id="foldersTree" value="#{recursiveTreeManager.getTree(treeKey)}" var="node" selectionType="client" toggleType="client">
                    <rich:treeNode iconClass="#{node.type}_Icon" expanded="#{node.expanded}" rendered="#{not node.hidden}">
                      <h:selectBooleanCheckbox value="#{node.selected}" id="checkBox" rendered="#{node.type ne 'NODE'}" />
                      <h:outputLabel for="checkBox" value="#{node.data.name}" rendered="#{node.type ne 'NODE'}" />
                      <h:outputText value="#{node.data.name}" rendered="#{node.type eq 'NODE'}" />
                    </rich:treeNode>
                  </rich:tree>
                  
                  
                  

                   

                  public class RecursiveTreeNode<DATA_TYPE extends TreeElement<DATA_TYPE>> extends TreeNodeImpl {
                      private DATA_TYPE data;
                      private NodeType type;
                      private RecursiveTreeNode<DATA_TYPE> parent;
                      private boolean selected = Boolean.FALSE;       // defines if node is selected in tree
                      private boolean expanded = Boolean.FALSE;       // defines if node is expanded
                  
                  
                      // NOTE: this attribute was named rendered
                      private boolean hidden = Boolean.FALSE;         // defines if node is filtered out
                  
                      // getters and setters
                  }
                  
                  
                  

                   

                  Before I had <rich:treeNode rendered="{node.rendered}" ... > and it kept crashing. Do you have any idea why?

                   

                  And my first question...why tree's getter is invoked even when aj4:command link with execute=@this and render=@this is clicked.

                  I've created a simple example, here is the link: https://www.dropbox.com/s/jpch5l2hfgg9lwb/rich_tree.zip Just click on 'executeThis' and you will se that treeBackingBean.tree is invoked twice.