10 Replies Latest reply on Apr 14, 2010 2:28 AM by katjuska

    rich:tree shrinking all the time

      Hi,

      I have a jsf-project which in I'm using rich:tree as a menu in the left side of the page.

      I am using Apache Tomcat 6.0, jre 1.6.0, mojarra 1.2, RichFaces 3.3.0.

       

      My problem is that the tree is shrinking all the time. Every time I click a link in the menutree and open a new page to the right side of the page, the whole tree is shrinking.

       

      I am also using same kind of tree in my program and it is working just fine. The only difference I can think of is that this menu tree in the left side of the page is allways opening a new page. The other menu tree is reloading the same page with different parameters.

       

      This is the link2open-funktion from the working menu:

       

       

      public void link2open() throws DAOException {

      setCls(getNodeTitle());

       

      FacesContext fc = FacesContext.getCurrentInstance();

      HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);

       

       

      session.setAttribute("product", classDAO.getProductNameByClass(cls));

       

      setShowEditView(true);

      setEditMode(false);

      //System.out.println("Class to open: " + nodeTitle.getCLS_NAME());

      }

       

       

      And this is the link2open from the non-working menu:

       

       

      public String link2open() {

      String toRet =

      "open_errorpage";

       

      if (tree.isRowAvailable()) {nodeTitle = (Menutree)tree.getRowData(); }

       

      setMenutree(getNodeTitle());

       

      // In here I am checking the correct page to be opened from the tree-information in this form "open_newpage"

      toRet =

      "open_newpage";

       

      //System.out.println("toRet: " + toRet);

       

      return toRet;

      }

       

       

       

       

      This is my tree2nav.xhtml:

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

      <html xmlns="http://www.w3.org/1999/xhtml"

      xmlns:ui="http://java.sun.com/jsf/facelets"

      xmlns:h="http://java.sun.com/jsf/html"  

      xmlns:f="http://java.sun.com/jsf/core"  

      xmlns:rich="http://richfaces.org/rich">

       

       

      <ui:composition>

       

       

       

      <h:form id="globaltreeForm">

      <h:panelGrid columns="2" width="100%" columnClasses="col1,col2">

       

       

       

      <rich:tree style="width:100px"

      nodeSelectListener="#{treeBacker.processSelection}"

       

      ajaxSubmitSelection="true"

       

      switchType="client"

       

      value="#{treeBacker.menuTree}"

       

      var="item"

      id="globaltree"

       

      treeNodeVar="rootNode"

       

      ajaxKeys="#{null}"

      nodeFace="leaf">

       

      <rich:treeNode type="leaf" icon="/images/iconLeaf_gif.gif">

       

      <h:commandLink actionListener="#{treeBacker.processAction}" value="#{item.MTR_LABEL}" immediate="true" action="#{treeBacker.link2open}" />

       

      </rich:treeNode>

       

      </rich:tree> 

       

      </h:panelGrid>

       

      </h:form>

      </ui:composition>

      </html>

       

       

       

       

       

       

       

       

       

       

       

       

       

       

      This is what I have in treeBacker.java:

       

      /**
      * License Agreement. JBoss RichFaces - Ajax4jsf Component Library Copyright (C)
      * 2007 Exadel, Inc. This library is free software; you can redistribute it
      * and/or modify it under the terms of the GNU Lesser General Public License
      * version 2.1 as published by the Free Software Foundation. This library is
      * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
      * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
      * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
      * details. You should have received a copy of the GNU Lesser General Public
      * License along with this library; if not, write to the Free Software
      * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      */

      package myController;

      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.Iterator;
      import java.util.List;
      import java.util.Map;
      import java.util.TreeMap;

      import javax.faces.component.UIComponent;
      import javax.faces.context.FacesContext;
      import javax.faces.event.AbortProcessingException;
      import javax.faces.event.ActionEvent;
      import javax.servlet.http.HttpSession;

      import misuDao.DAOException;
      import myPackage.Menutree;

      import org.richfaces.component.html.HtmlTree;
      import org.richfaces.event.NodeSelectedEvent;
      import org.richfaces.model.TreeNode;
      import org.richfaces.model.TreeNodeImpl;


      public class TreeBacker extends AbstractTreeBackerForm {
      public static final String versionNo = "0.1";

      myController.UserRights UserRights = new myController.UserRights();
      private String value = null;
      private TreeNode<Menutree> rootNode = null;
      //private List<String> selectedNodeChildren = new ArrayList<String>();
      private List<Menutree> selectedNodeChildren = new ArrayList<Menutree>();
      ArrayList<String> treefolders;
      private Menutree menutree = new Menutree();
      private HtmlTree tree = new HtmlTree();

      private Long listType;
      private String projectPageType;

      private Menutree nodeTitle;

      private void addNodes(String path, TreeNode<Menutree> node, TreeMap<String, Menutree> tr) {
        boolean end = false;
        int counter = 1;
        while (!end) {
         String key = path != null ? path + '.' + counter : String.valueOf(counter);
         Menutree value = tr.get(key);
         if (value != null) {
          System.out.println("Key:" + key + " - Name: " + value.getMTR_LABEL());
          TreeNodeImpl<Menutree> nodeImpl = new TreeNodeImpl<Menutree>();
          nodeImpl.setData(value);
          node.addChild(new Integer(counter), nodeImpl);
          addNodes(key, nodeImpl, tr);
          counter++;
         } else {
          end = true;
         }
        }
      }

      private void loadMenuTree() {
        rootNode = new TreeNodeImpl<Menutree>();
        addNodes(null, rootNode, menutreeDAO.createNewInstanceOfKey());
      }


      public void processSelection(NodeSelectedEvent event) {
        HtmlTree tree = (HtmlTree) event.getComponent();
        nodeTitle = (Menutree) tree.getRowData();
        selectedNodeChildren.clear();
        TreeNode<Menutree> currentNode = tree.getModelTreeNode(tree.getRowKey());
        if (currentNode.isLeaf()) {
         selectedNodeChildren.add(currentNode.getData());
        } else {
         Iterator<Map.Entry<Object, TreeNode<Menutree>>> it = currentNode.getChildren();
         while (it != null && it.hasNext()) {
          Map.Entry<Object, TreeNode<Menutree>> entry = it.next();
          selectedNodeChildren.add(entry.getValue().getData());
          System.out.println(entry.getValue().getData().getMTR_LABEL().getValue());
         }
        }
      }

       

       

      public void processAction(ActionEvent event) throws AbortProcessingException {
        UIComponent component = (UIComponent) event.getSource();
        while (!(component != null && component instanceof HtmlTree)) {
         component = component.getParent();
        }
        if (component != null) {
         HtmlTree tree = (HtmlTree) component;
         nodeTitle = (Menutree) tree.getRowData();
         System.out.println("nodeTitle:"+nodeTitle.getMTR_LABEL().getValue());
        }
      }

       

      /**
        * Defains which page will be opened when clicked from the tree menu
        *
        * @return toRet is the navigation string for faces-config.xml
        */
      public String link2open() {
        String toRet = "open_errorpage";
       
        if (tree.isRowAvailable()) {
         nodeTitle = (Menutree)tree.getRowData();
        }
       
        setMenutree(getNodeTitle());

        if (menutree.getPRO_ID().getValue() != 0L) {
         // Set current, selected projectId to session
         HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
         session.setAttribute("projectid", menutree.getPRO_ID().getValue());
         try {
          session.setAttribute("projectname", userDAO.getNameOfProject(menutree.getPRO_ID().getValue()));
          session.setAttribute("product", userDAO.getProductOfProject(menutree.getPRO_ID().getValue()));
          session.setAttribute("subprojects", userDAO.getSubProjects(menutree.getPRO_ID().getValue()));
          System.out.println("SESSION PROJECTINFO:"+session.getAttribute("projectid")+":"+session.getAttribute("projectname")+":"+session.getAttribute("subprojects"));
         } catch (DAOException e) {
          e.printStackTrace();
         }
        }

        if (menutree.getRIG_ID().getValue() != 0L) {
         boolean right = false;
         if (menutree.getPRO_ID().getValue() != 0L) {
          right = UserRights.CheckIfUserHasRight(menutree.getRIG_ID().getValue(), myController.UserRights.RIGHT_TYPE_VIEW);   
         } else {
          right = UserRights.CheckIfUserHasRight(menutree.getRIG_ID().getValue(), myController.UserRights.RIGHT_TYPE_VIEW, 0L, true);
         }
         if (right) {
          if (menutree.getJTG_COMMAND().getValue() != null && !menutree.getJTG_COMMAND().getValue().equals("")) {
           toRet = menutree.getJTG_COMMAND().getValue();
          } else {
           toRet = "open_errorpage";
          }
         } else {
          toRet = "open_norightpage";
         }
        } else {
        }
       
        return toRet;
      }

      public String goTo(String ret) {

        HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
          .getExternalContext().getSession(false);
        session.setAttribute("pagetoopen", ret);
        return ret;
      }

      public String getValue() {
        return value;
      }

      public void setValue(int valor) {
        this.value = treefolders.get(valor);
        System.out.println("this.value: " + this.value);
      }

       

      public TreeNode<Menutree> getMenuTree() {
        if (rootNode == null) {
         loadMenuTree();
        }
        return rootNode;
      }

      public Menutree getNodeTitle() {
        return nodeTitle;
      }

      public void setNodeTitle(Menutree nodeTitle) {
        this.nodeTitle = nodeTitle;
      }

      public void setListType(Long listType) {
        this.listType = listType;
      }

      public Long getListType() {
        return listType;
      }

      public Menutree getMenutree() {
        return menutree;
      }

      public void setMenutree(Menutree menutree) {
        this.menutree = menutree;
      }

      public HashMap<String,String> getArguments(String arguments) {
        HashMap<String,String> arg = new HashMap<String,String>();
       
        try {
         if (arguments != null && !arguments.equals("")) {
          String[] values = arguments.split(";");
          if (values.length > 0) {
           for (int i=0; i<values.length; i++) {
            String[] temp = values[i].split("=");
            if (temp.length > 1) {
             arg.put(temp[0], temp[1]);
            }
           }
          }
         }
        } catch (Exception e) {
         e.printStackTrace();
        }
       
        return arg;
      }

      public void setTree(HtmlTree tree) {
        this.tree = tree;
      }

      public HtmlTree getTree() {
        return tree;
      }

      public void setProjectPageType(String projectPageType) {
        this.projectPageType = projectPageType;
      }

      public String getProjectPageType() {
        return projectPageType;
      }

      }

       

       

       

      I would really appreciate any help, any new ideas what might be causing the problem.

       

      Thanks, Katja

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

        • 1. Re: rich:tree shrinking all the time
          ilya_shaikovsky

          <h:commandLink actionListener="#{treeBacker.processAction}" value="#{item.MTR_LABEL}"immediate="true" action="#{treeBacker.link2open}" />

          with usage of h:command component - full page reload is expected result.

           

          Or I missed something?

          • 2. Re: rich:tree shrinking all the time

            Actually in the other part of my page I have the other tree that is working correctly and there I am also using the same component..

             

            Here is the code from the working tree:

             

            <

            rich:tree style="width:100px"

             

            nodeSelectListener="#{classesBean.processSelection}"

             

            ajaxSubmitSelection="true"

             

            switchType="client"

             

            value="#{classesBean.classesTree}"

             

            var="item"

             

            id="treeclass"

             

            treeNodeVar="treeNode"

             

            ajaxKeys="#{null}"

             

            nodeFace="leaf">

             

            <rich:treeNode type="leaf" icon="/images/iconLeaf_gif.gif">

             

            <h:graphicImage value="/images/lock.png" rendered="#{item.locked}" id="lockedFlag"/>

             

            <h:graphicImage value="/images/verify.gif" rendered="#{item.verified}" id="verifiedFlag"/>

             

            <h:commandLink actionListener="#{classesBean.processAction}" value="#{item.CLS_NAME}" immediate="true" action="#{classesBean.link2open}" />

             

            </rich:treeNode>

             

            </rich:tree>

            • 3. Re: rich:tree shrinking all the time
              ilya_shaikovsky

              sorry, now seems get your point. You mean that nodes became collapsed and selection not preserved? Then you should check adviceNodeOpened and adviceNodeSelected attributes. Or treeStateAdvisor instead of both.

              • 4. Re: rich:tree shrinking all the time

                Ilya Shaikovsky wrote:

                 

                sorry, now seems get your point. You mean that nodes became collapsed and selection not preserved? Then you should check adviceNodeOpened and adviceNodeSelected attributes. Or treeStateAdvisor instead of both.

                Yes. Now you got my point. The problem is that the nodes became collapsed and selection not preserved. Sorry, my bad explanation.

                 

                Could you give me some more detailed example how to use the attributes you mentioned?

                I'm quite new with jsf, this is the first project that I'm working with jsf. I have been working earlier with Java servlets.

                 

                Thanks, Katja

                • 5. Re: rich:tree shrinking all the time
                  ilya_shaikovsky

                  This methods should get node as parameter and return if the particular node is collapsed or expanded and if it's selected.

                  simple sample there http://livedemo.exadel.com/richfaces-demo/richfaces/treeNodesAdaptor.jsf?c=recursiveTreeNodesAdaptor&tab=usage. check View TreeDemoStateAdvisor.java Source source link. it's just already makes first two levels of tree expanded. And in your case - you should remember current selection node and preserve it's selection and expand parent ones.

                  • 6. Re: rich:tree shrinking all the time

                    In the example there is used PostbackPhaseListener.java. Could you explain me why?

                    I don't quite understand what for example this is:

                     

                    public static final String POSTBACK_ATTRIBUTE_NAME = PostbackPhaseListener.class.getName();

                     

                    I now added my tree to be like this:

                     

                     

                    <rich:tree stateAdvisor=

                    "#{treeMenuStateAdvisor}"

                     

                     

                     

                    adviseNodeOpened=

                    "#{treeBacker.adviseNodeOpened}"

                     

                     

                     

                    style=

                    "width:100px"

                     

                     

                     

                    nodeSelectListener=

                    "#{treeBacker.processSelection}"

                     

                     

                     

                    ajaxSubmitSelection="true" switchType=

                    "client"

                     

                     

                     

                    value="#{treeBacker.menuTree}" var="item" id=

                    "globaltree"

                     

                     

                     

                    treeNodeVar="rootNode" ajaxKeys="#{null}" nodeFace="leaf"

                    >

                     

                     

                     

                    <rich:treeNode type="leaf" icon="/images/iconLeaf_gif.gif"

                    >

                     

                     

                     

                    <h:commandLink actionListener=

                    "#{treeBacker.processAction}"

                     

                     

                     

                    value="#{item.MTR_LABEL}" immediate=

                    "true"

                     

                     

                     

                    action="#{treeBacker.link2open}"

                    />

                     

                     

                     

                    </rich:treeNode

                    >

                     

                     

                     

                    </rich:tree

                    >

                     

                    And I added to the bean (TreeBacker.java) this method:

                     

                     

                     

                    public void

                    adviseNodeOpened(UITree tree) {

                    System.

                     

                    out.println("treeBacker.adviseNodeOpened"

                    );

                     

                     

                    treeMenuStateAdvisor

                    .adviseNodeOpened(tree);

                     

                     

                    treeMenuStateAdvisor

                    .adviseNodeSelected(tree);

                     

                     

                    And then I added the same kind of TreeMenuStateAdvisor.java as in the example:

                     

                     

                    package

                     

                     

                    myController;

                     

                    import

                     

                     

                    org.richfaces.component.UITree;

                    import

                     

                     

                    org.richfaces.component.state.TreeStateAdvisor;

                    import

                     

                     

                    org.richfaces.model.TreeRowKey;

                     

                    public

                     

                     

                    class TreeMenuStateAdvisor implements

                    TreeStateAdvisor {

                     

                     

                     

                    public

                    Boolean adviseNodeOpened(UITree tree) {

                    System.

                     

                    out.println("TreeMenuStateAdvisor.adviseNodeOpened"

                    );

                     

                     

                    if

                    (!PostbackPhaseListener.isPostback()) {

                    System.

                     

                    out.println("PostbackPhaseListener.isPostback"

                    );

                    Object key = tree.getRowKey();

                    TreeRowKey treeRowKey = (TreeRowKey) key;

                     

                     

                    if (treeRowKey == null

                    || treeRowKey.depth() <= 2) {

                     

                     

                    return Boolean.TRUE

                    ;

                    }

                    }

                     

                     

                     

                    return null

                    ;

                    }

                     

                     

                     

                    public

                    Boolean adviseNodeSelected(UITree tree) {

                     

                     

                    return null

                    ;

                     

                     

                     

                     

                    The tree is still working the same way as earlier. It never goes through the

                    if

                     

                     

                     

                    if-statement in the TreeMenuStateAdvisor.

                     

                    So I still don't get everything right...

                    • 7. Re: rich:tree shrinking all the time
                      nbelaevski

                      Hi Katja,

                       

                      In the demo it's used to get several levels of tree expanded on initial rendering.

                      Here is the check for node depth:

                       

                      if (treeRowKey == null || treeRowKey.depth() <= 2) {
                           return Boolean.TRUE;
                      }
                      
                      
                      • 8. Re: rich:tree shrinking all the time

                        Hi Nick,

                         

                        That is the same code that I was using.. 

                         

                        It still isn't working. Any ideas how to solve the problem?

                        I earlier tryied to describe the changes I made to my code based on the example.

                         

                        Thanks for any help, Katja

                        • 9. Re: rich:tree shrinking all the time
                          nbelaevski

                          Katja,

                           

                          There's "componentState" attribute at rich:tree that allows to wire information about component state to bean. Try binding component state of both trees to the same session-scoped bean property.

                          • 10. Re: rich:tree shrinking all the time

                            Nick,

                            Thank you, thank you, thank you.

                            You saved my day. The simpliest solutions are usually the best ones.

                             

                            All I needed to do was to add this to my tree:

                            componentState ="#{treeBacker.treeState}"

                             

                            And this to my bean:

                             

                            And now the tree is working just the way it was supposed to be.

                            Thanks for all the help, Katja

                            private

                             

                             

                            TreeState treeState;

                             

                             

                             

                             

                             

                            public

                             

                             

                            TreeState getTreeState() {

                             

                            return treeState;

                            }

                             

                             

                            public void setTreeState(TreeState treeState) {

                             

                            this.treeState = treeState;

                            }