8 Replies Latest reply on Aug 26, 2008 10:19 AM by Coral Featherstone

    two tree problems

    Coral Featherstone Newbie

      I am using richfaces with seam.
      The tree is mostly working, but I am experiencing two problems.
      1) The first is that the tree's nodeSelectListener mostly works, but every now and then the event just does not get fired and the page needs to be reloaded before it will work again. There are no obvious exceptions being thrown.
      2) The second problem involves programatically expanding the tree.
      I am binding the tree to a seam component and trying to keep the tree expanded in sync with a <a4j:commandLink/> on a separate part of the page, but when the commandLink is called the tree's rowKey is null and calling tree.queueNodeExpand(new ListRowKey(arrayList)); throws an illegalStateException "No tree element available or row key not set".
      As an aside rowKey send in the nodeselectionListener event's tree is not null.
      I have tried changing the scope of the binding to no avail.

      How can I expand the tree from a link outside of the tree?
      The same code breaks trying to get the tree expanding only the first level while populating the initial TreeNode's.

      Parts of Relevant code follows:
      page:

      <rich:tree style="width:180px;overflow: scroll;overflow-y:hidden"
       nodeSelectListener="#{conceptViewBacking.processSelection}"
       ajaxSubmitSelection="true" switchType="ajax"
       rendered="#{strategyMapPanelBacking.showConceptViewComponents}"
       value="#{conceptViewBacking.treeHolder}" var="item"
       nodeFace="#{item.type}" reRender="conceptForm"
       binding="#{treeBinding.tree}"
       ajaxSingle="true"
       id="conceptTree"
       >
      
       <rich:treeNode type="strategy"
       iconLeaf="../img/conceptview/strategy.png"
       icon="../img/conceptview/strategy.png" reRender="conceptDetail"
       id="strategyTreeNode">
       <h:outputText value="#{item.name}" />
       </rich:treeNode>
      
       <rich:treeNode type="vertical"
       iconLeaf="../img/conceptview/vertical.gif"
       icon="../img/conceptview/vertical.gif"
       id="verticalTreeNode">
       <h:outputText value="#{item.name}" reRender="conceptDetail"/>
       </rich:treeNode>
       </rich:tree>
      


      commandLinkAction:

      @In(create = true)
       TreeBinding treeBinding;
      
      public void expandTreeAboveStrategy(StrategyBubble sBubble) {
       ArrayList<Long> arrayList = new ArrayList<Long>();
       ///... code to collecting rowKeys
       try {
       HtmlTree tree = getTreeBinding().getTree();
       final Object rowKey = tree.getRowKey();//null
      
       tree.queueNodeExpand(new ListRowKey(arrayList));//error
       } catch (IOException e) {
       FacesUtil.sendInfoMsg("problem expanding tree");
       e.printStackTrace();
       }
       }


      binding:
      @Name("treeBinding")
      @Scope(ScopeType.EVENT)
      public class TreeBinding {
      
       private HtmlTree tree;
      
       public HtmlTree getTree() {
       return tree;
       }
      
       public void setTree(HtmlTree tree) {
       this.tree = tree;
       }
      }



        • 1. Re: two tree problems
          Coral Featherstone Newbie

          Does anyone at least know what causes the illegalStateException "No tree element available or row key not set". exception in the above?

          • 2. Re: two tree problems
            Kerdudou Ronan Apprentice

            Perhaps this will help:

            I had the same illegalStateException "No tree element available or row key not set"

            and i had to remove the
            ajaxSingle="true"and immediate="true" from my rich:tree.

            • 3. Re: two tree problems
              Coral Featherstone Newbie

              Mmmm. I must be doing something else wrong! I reduced the tree to bare minimum

              <rich:tree
               value="#{conceptViewBacking.treeHolder}" var="item"
               binding="#{treeBinding.tree}"
               id="conceptTree"
               >
              </rich:tree>

              still get
              9:49:11,847 ERROR [ExceptionFilter] handling uncaught exception
              javax.servlet.ServletException: No tree element available or row key not set!
               at javax.faces.webapp.FacesServlet.service(FacesServlet.java:256)
               at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
               at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
               at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
               at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:85)
               at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
               at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
               at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
               at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:44)
               at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
               at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:73)


              If it helps I am also trying to expand the first level of nodes right after creating the tree with the same code

              UITree tree = getTreeBinding().getTree();
              TreeState ts = (TreeState) tree.getComponentState();
              ListRowKey listRowKey = new ListRowKey(arrayList);
              tree.queueNodeExpand(listRowKey); //ignored nothing happens
              //ts.expandNode(tree, listRowKey); //throws row key not set error
              

              and here queueNodeExpand doesn't throw the errors but it doesn't expand the tree either.

              • 4. Re: two tree problems
                Kerdudou Ronan Apprentice

                I can't help you. I'm not using any bindings nor rowkeys on my tree.

                I have implemented the following interface:
                TreeStateAdvisor, NodeExpandedListener, NodeSelectedListener

                And I use them in my tree

                <rich:tree ...
                stateAdvisor="#{myBean.treeAdvisorImpl}"
                nodeSelectListener="#{myBean.NodeSelectedListenerImpl}"
                ...


                • 5. Re: two tree problems
                  Coral Featherstone Newbie

                  But your suggestion has given me some ideas. I thought it might be because the tree was on a rich:tabPanel, but moving it off also made no difference. Oh well, will keep trying :~P. Thanks for the suggestion. Much appreciated.

                  • 6. Re: two tree problems
                    Nick Belaevski Master

                     

                    "coralfe" wrote:
                    Does anyone at least know what causes the illegalStateException "No tree element available or row key not set". exception in the above?


                    That happens when element can not be found for the given row key.

                    Can you please create a small sample demo application to see the issue?
                    You can send it to me to nbelaevski - exadel com

                    • 7. Re: two tree problems
                      Coral Featherstone Newbie

                      Thank you very much

                      • 8. Re: two tree problems
                        Coral Featherstone Newbie

                        Firstly thanks for all the help.

                        I had two minor errors in my code. The first one a

                        Collections.reverse(arrayList);
                        fixed my error.

                        I am going to summarize some of what I picked up here (right or wrong) since the documentation is minimal and it is very time consuming to find this information. Maybe it will help someone.

                        1)The tree has a base root node that is not displayed, so if you want a tree with one root node, it programmatically has two.

                        2) Rowkeys
                        The call to [TreeNode].addChild([some key], childNode);
                        sets up your rowKeys.
                        so for example

                        TreeNodeImpl rootNode = new TreeNodeImpl();
                        rootNode.setData(...something ....);
                        
                        TreeNodeImpl firstChild = new TreeNodeImpl();
                        firstChild.setData(...something ....);
                        rootNode.addChild(1L, firstChild);
                        
                        TreeNodeImpl secondChild = new TreeNodeImpl();
                        secondChild.setData(...something ....);
                        firstChild.addChild(2L, secondChild);
                        

                        The above tree has only two visible nodes, namely:-
                        the root node (first child) with rowkey "1"
                        and its child (secondChild) with rowkey "1:2"

                        One way to programatically expand nodes its to get hold of the tree either a) through the event parameter of the nodeSelectListener attribute on the tree or b) by binding the tree to your backing bean.

                        btw nodeSelectListener requires the ajaxSubmitSelection="true" attribute.

                        a) nodeSelection listener points at a method something like

                        public void processSomething(NodeSelectedEvent event) {
                        
                         UITree tree = getTree(event);
                        Object rowData = tree.getRowData();
                         ... do something ...
                        
                        }


                        Once you have your tree there are two ways to expand nodes either
                        ListRowKey listRowKey = new ListRowKey(arrayList);
                        tree.queueNodeExpand(listRowKey);

                        or
                        ListRowKey listRowKey = new ListRowKey(arrayList);
                        TreeState ts = (TreeState) tree.getComponentState();
                        ts.expandNode(tree, listRowKey)


                        the latter worked for me.

                        Now one of the ListRowKey constructors takes a List (Collection) of keys.
                        These are all the keys for ONE node.
                        So for example to expand the root node (first child) with rowkey "1" the collection contains one Long (or whatever object type you passed to addChild) and to expand secondChild with rowkey "1:2" the list containers two Longs, but very importantly the 1L needs to be added before the 2L as the collection order is important (hence the frequent use of Collections.reverse(arrayList); )

                        3) Expanding just the rootNode will expand rootNode so that you can see its children.
                        4)You may need to expand unexpanded parent nodes of a node to see the expansion.

                        5) I had to call rerender on my tree when expanding outside the listener to view the expansion.

                        As mentioned, hope this helps someone.