1 Reply Latest reply on Oct 25, 2008 3:30 PM by djheath

    Desperately Seeking Tree Control Help

    djheath

      Okay,

      After trying to duplicate the online examples of the tree control, I'm at a loss. I'm reasonably familiar with JSF/Richfaces but brand new to the tree control.

      Very similar to the artist/album/singer online example, I have an analogous application/subcontext/exclude model.

      The code executes on the ApplicationNode.getData (I've stepped through it with the debugger) but the tree is entirely empty when it renders.

      Here's the relevant snippet from SimpleTreeNode:

       public TreeNode getTreeNode() {
       if (rootNode == null) {
       loadTree();
       }
      
       return rootNode;
       }
      
       private void loadTree() {
       List<ApplicationBean> list = activityService.getApplications();
       rootNode = new TreeNodeImpl();
      
       for (ApplicationBean bean : list) {
       ApplicationNode node = new ApplicationNode(bean);
       node.setParent(rootNode);
       rootNode.addChild(bean.getApplicationId(), node);
       }
      
       }
      
      


      And yes, the list IS populated when it comes back from the service call. All this seems reasonable so far.

      Next is the def'n for my ApplicationNode:
      public class ApplicationNode extends BaseTreeNode {
       private static final long serialVersionUID = -4724947051841699837L;
       private Map<Long, SubContextNode> children = new HashMap<Long, SubContextNode>();
      
       public ApplicationNode(ApplicationBean bean) {
       data = bean;
       this.type="application";
       }
      
       public void addChild(Object key, TreeNode child) {
       child.setParent(this);
       children.put((Long)key, (SubContextNode) child);
       }
      
       public TreeNode getChild(Object key) {
       return children.get(key);
       }
      
       public Iterator getChildren() {
       return children.entrySet().iterator();
       }
      
       public TreeNode getParent() {
       return null;
       }
      
       public boolean isLeaf() {
       return false;
       }
      
       public void removeChild(Object key) {
       this.children.remove(key);
       }
      
       public void setParent(TreeNode parent) {
       }
      
       public String toString() {
       return ((ApplicationBean) data).getDescription();
       }
      }
      


      and its base class, BaseTreeNode:
      public abstract class BaseTreeNode implements TreeNode {
       protected final Log logger = LogFactory.getLog(getClass());
       protected Object data;
       protected String type = "root";
      
       public Object getData() {
       return this;
       }
      
       public void setData(Object data) {
       }
      
       public void addChild(Object arg0, TreeNode arg1) {
       throw new AbstractMethodError(this.getClass() + "addChild: Abstract Method Error");
       }
      
       public TreeNode getChild(Object arg0) {
       throw new AbstractMethodError(this.getClass() + "getChild: Abstract Method Error");
       }
      
       public Iterator getChildren() {
       throw new AbstractMethodError(this.getClass() + "getChildren: Abstract Method Error");
       }
      
       public boolean isLeaf() {
       throw new AbstractMethodError(this.getClass() + "isLeaf: Abstract Method Error");
       }
      
       public void removeChild(Object arg0) {
       throw new AbstractMethodError(this.getClass() + "removeChild: Abstract Method Error");
       }
      
       public TreeNode getParent() {
       throw new AbstractMethodError(this.getClass() + "getParent: Abstract Method Error");
       }
      
       public void setParent(TreeNode arg0) {
       throw new AbstractMethodError(this.getClass() + "setParent: Abstract Method Error");
       }
      
       public String getDisplayText() {
       logger.info(data);
       return toString();
       }
      
       public String getType() {
       logger.info(this.type);
       return this.type;
       }
      }
      


      The other two Node types (SubContextNode & ExcludeNode) are essentially the same but return a different type.

      Finally, my xhtml file:

      <?xml version="1.0" encoding="UTF-8"?>
      <!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" xml:lang="en" lang="en"
       xmlns:a4j="http://richfaces.org/a4j"
       xmlns:rich="http://richfaces.org/rich">
      
       <body>
       <f:view>
       <h:form>
       <rich:tree id="objectTree" style="width:500px"
       value="#{simpleTreeBean.treeNode}" var="item"
       nodeFace="#{item.type}" >
       <rich:treeNode type="application" icon="images/application.png" >
       <h:outputText value="#{item.displayText}" />
       </rich:treeNode>
       <rich:treeNode type="subcontext" icon="images/subcontext.png">
       <h:outputText value="#{item.displayText}" />
       </rich:treeNode>
       <rich:treeNode type="exclude" iconLeaf="images/exclude.png">
       <h:outputText value="#{item.displayText}" />
       </rich:treeNode>
       </rich:tree>
       </h:form>
       </f:view>
       </body>
      </html>
      
      


      So it all looks very similar to the posted demos, but alas with no tree nodes rendering. Can anyone point me in the right direction??? Thanks

      -djh


        • 1. Re: Desperately Seeking Tree Control Help
          djheath

          So I got it working. Apparently the problem was with my derivative ApplicationNode class. I refactored the BaseTreeNode class to have most of the TreeNode methods in it and voila! It works.

          Code snippets below for reference:

          BaseTreeNode:

          
          import java.util.Iterator;
          import java.util.LinkedHashMap;
          import java.util.Map;
          
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;
          import org.richfaces.model.TreeNode;
          
          @SuppressWarnings("unchecked")
          public abstract class BaseTreeNode implements TreeNode {
           protected final Log logger = LogFactory.getLog(getClass());
           protected TreeNode parent;
           protected Object data;
           protected String type;
           protected Map<Object, TreeNode> children = new LinkedHashMap<Object, TreeNode>();
          
           public Object getData() {
           return this;
           }
          
           public void setData(Object data) {
           }
          
           public void addChild(Object identifier, TreeNode child) {
           child.setParent(this);
           children.put(identifier, child);
           }
          
           public TreeNode getChild(Object key) {
           return children.get(key);
           }
          
           public Iterator getChildren() {
           return children.entrySet().iterator();
           }
          
           public TreeNode getParent() {
           return parent;
           }
          
           public boolean isLeaf() {
           return children.isEmpty();
           }
          
           public void removeChild(Object key) {
           TreeNode node = this.children.remove(key);
           if (null != node)
           node.setParent(null);
           }
          
           public void setParent(TreeNode parent) {
           this.parent = parent;
           }
          
           public String getType() {
           return this.type;
           }
          }
          
          


          ApplicationNode (derived class):
          
          @SuppressWarnings("unchecked")
          public class ApplicationNode extends BaseTreeNode {
           private static final long serialVersionUID = -4724947051841699837L;
          
           public ApplicationNode(ApplicationBean bean) {
           data = bean;
           this.type="application";
           }
          
           public String toString() {
           return ((ApplicationBean) data).getDescription();
           }
          }
          
          


          And the associated xhtml:
          <?xml version="1.0" encoding="UTF-8"?>
          <!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" xml:lang="en" lang="en"
           xmlns:a4j="http://richfaces.org/a4j"
           xmlns:rich="http://richfaces.org/rich">
          
           <head>
           <title>Tree Example</title>
           <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
          
           <!--<link rel="stylesheet" type="text/css" href="styles.css">-->
           </head>
           <body>
           <f:view>
           <h:form>
           <rich:tree id="objectTree" style="width:500px"
           value="#{simpleTreeBean.treeNode}" var="item"
           nodeFace="#{item.type}" >
           <rich:treeNode type="application" icon="images/application.png" iconLeaf="images/application.png">
           <h:outputText value="#{item}" />
           </rich:treeNode>
           <rich:treeNode type="subcontext" icon="images/subcontext.png" iconLeaf="images/subcontext.png">
           <h:outputText value="#{item}" />
           </rich:treeNode>
           <rich:treeNode type="exclude" iconLeaf="images/exclude.png">
           <h:outputText value="#{item}" />
           </rich:treeNode>
           </rich:tree>
           </h:form>
           </f:view>
           </body>
          </html>
          
          

          Hope this helps someone avoid the same pitfall I fell into. Ciao!