4 Replies Latest reply on Jun 1, 2009 9:45 AM by Prathamesh Gaddam

    recursiveTreeNodesAdaptor - dynamic loading Problem

    heapifyman heapifyman Newbie

      I have a question regarding rich:tree component. I'm just trying to get to know the tree component. I have created a single entity bean that has a parent-child relationship with itself and want to display that structure in a rich:tree. I found the recursiveTreeNodesAdaptor example and got it working: tree is correctly displayed and expands and collapses alright. Now to my question: I've noticed that apparently on every collapse/expand the whole tree is reloaded, i.e. there are a lot of database accesses. For my little example that works fine but I suppose for more complex entities and a lot more entries in the database that could be a performance problem. What I'd like to have is that only the part of the tree that is expanded is reloaded. How would I accomplish that? I've found the ajaxSingle attribute but setting it to true didn't change anything. Any hints would be appreciated. Thanks. Here my code so far:

      <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <ui:composition xmlns="http://www.w3.org/1999/xhtml"
       xmlns:s="http://jboss.com/products/seam/taglib"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:f="http://java.sun.com/jsf/core"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:rich="http://richfaces.org/rich"
       xmlns:a4j="http://richfaces.org/a4j"
       template="layout/template.xhtml">
      
      <ui:define name="body">
      
       <rich:panel>
       <f:facet name="header">TreeTest</f:facet>
       <h:form>
       <rich:tree id="treeTestTree"
       switchType="ajax"
       ajaxSingle="true"
       adviseNodeOpened="#{treeTestList.adviseNodeOpened}">
       <rich:recursiveTreeNodesAdaptor
       id="treeTestRecursiveTreeNodesAdaptor"
       roots="#{treeTestList.rootNodes}"
       var="_treeTest"
       nodes="#{_treeTest.children}" >
       <rich:treeNode>
       <h:outputText value="#{_treeTest.name}" />
       </rich:treeNode>
       </rich:recursiveTreeNodesAdaptor>
       </rich:tree>
       </h:form>
       </rich:panel>
      
      </ui:define>
      
      </ui:composition>
      


        • 1. Re: recursiveTreeNodesAdaptor - dynamic loading Problem
          Nick Belaevski Master

          Hello,

          What I'd like to have is that only the part of the tree that is expanded is reloaded.


          That's how tree works out of the box. You do not have to use ajaxSingle for that.

          • 2. Re: recursiveTreeNodesAdaptor - dynamic loading Problem
            heapifyman heapifyman Newbie

             

            That's how tree works out of the box. You do not have to use ajaxSingle for that.


            Well apparently it doesn't do that for me. As you can see in my first posting, I use
            roots="#{treeTestList.rootNodes}"
            to load the root nodes.
            The Java code looks like this (maybe I'm doing something wrong here):
            public List<TreeTest> getRootNodes()
             {
             if (rootNodes.isEmpty()) {
             rootNodes = getRootChildren();
             }
             return rootNodes;
             }

            where rootNodes is
            private List<TreeTest> rootNodes = new ArrayList<TreeTest>();

            and getRootChildren() just does
            return (List<TreeTest>) getEntityManager().createQuery(GET_ROOTNODES).getResultList();

            with
            private static final String GET_ROOTNODES = "select treeTest from TreeTest treeTest where treeTest.parent is null";

            And whenever I expand or collapse any part of the tree, I can clearly see the following statement in my logs:
            select
             treetest0_.ID as ID1_,
             treetest0_.NAME as NAME1_,
             treetest0_.PARENT_FK as PARENT3_1_
             from
             mme.TREE_TEST treetest0_
             where
             treetest0_.PARENT_FK is null

            followed by a lot more SQL queries.

            That's what I'm trying to avoid here, all the db accesses when expanding/collapsing the tree.

            Thanks for any hints.

            • 3. Re: recursiveTreeNodesAdaptor - dynamic loading Problem
              Nick Belaevski Master

              In fact, it does, but not in the way you expected.

              The nature of tree node adaptors (either recursive or not) is that these components are evaluating EL-expression in order to proceed to the next level of iteration. For example, we have a recursiveTreeNodeAdaptor with roots="bean.roots", var="node" and children="node.children". Imagine that you've expanded /node[1]/node[3]/node[4]. This is equivalent to evaluating such expression: (((((bean.roots)[1]).children)[3]).children)[4]. That's the reason why nodes collections are requested.

              How you can deal with this: there is the difference in methods called. For sequential iteration the list#iterator() method is called, and for traversal to i-th node, list#get(i) method is called (note that list#get(i) is also called for sequential iteration, after list#iterator() call). Proposed workaround: create an extension of list that will use this difference and either does the query for all nodes (if iterator() was called), or just the concrete node (if get(i) is called).

              • 4. Re: recursiveTreeNodesAdaptor - dynamic loading Problem
                Prathamesh Gaddam Novice

                 

                "nbelaevski" wrote:
                Proposed workaround: create an extension of list that will use this difference and either does the query for all nodes (if iterator() was called), or just the concrete node (if get(i) is called).


                Hi Nick, may I have the elaboration on your reply!