Another JSF project I've been working on required another dynamic JSF tree. However, this time the component library being used was IceFaces. If you recall, the last time I used RichFaces. I have to say that using IceFaces made this task MUCH easier.
The basic setup:
- A "tree" structure that is made up of "node" objects. Each node has a parent node as well as a list of child nodes. Root nodes have a null parent. The tree object takes a list of root nodes. (see code below)
- A JSF Tree. IceFaces was used this time. (see code below)
- A JSF managed backing bean with ActionListeners and DAO access. ActionListeners are used for the CRUD operations on nodes. DAO access is used for directly updating the objects in the database. (see code below)
- A great place to start is with one of IceFaces tree examples. I used this one: IceFaces Sample Tree Application
All of this sounds very familiar, right?
Here's where it starts to get different.
The Tree UI:
<ice:panelGroup style="border: 1px solid gray;">
<ice:tree id="tree"
value="#{tree.model}"
var="item"
hideRootNode="false"
hideNavigation="false"
>
<ice:treeNode>
<f:facet name="content">
<ice:panelGroup style="display: inline">
<ice:commandLink
actionListener="#{item.userObject.nodeClicked}"
value="#{item.userObject.label}"/>
</ice:panelGroup>
</f:facet>
</ice:treeNode>
</ice:tree>
</ice:panelGroup>
Note that "tree.model" is passed in. Also note that there is a commandLink with actionListener. This sets the selected node id on the backing bean. Both of these things can be seen in the IceFaces sample tree application referenced above.
What you'll need to do to make this truly dynamic is add some controls to your tree display page and some backing bean methods. I'll use adding a node as an example.
Add the code below to the page that displays the tree. newNodeName is a field on the backing bean. addChildToSelectedNode is the method on the backing bean that takes "newNodeName", creates a node, and persists it to the database.
<div id="addNode">
<table width="100%">
<tr>
<td><ice:outputText value="Name:"/></td>
<td><ice:inputText value="#{nodeManagement.newNodeName}"/></td>
</tr>
<tr>
<td>
<ice:commandButton
value="Add Child to Selected Node"
action="#{nodeManagement.addChildToSelectedNode}"
partialSubmit="true"/>
</td>
</tr>
</table>
</div>
<ice:outputText
value="Selected Node: #{tree.selectedNodeObject.label}"
escape="false" style="font-weight:bold;"/>
The method that add a node to the tree is shown below. Note the last line (tree.buildTreeModel()). This rebuilds the tree model that used to display the tree. If this method is not implemented on the Tree bean, you will have to refresh the page manually to see the node that was just created.
public void addNodeToSelectedNode() {
//you'll probably want to handle errors here
//selectedNodeId can't be blank or null
//newNodeName shouldn't be blank or null
Node newNode = new Node();
//load the selectedNode using the selectedNodeId
Node selectedNode = nodeDao.load(selectedNodeId);
//get the selected node's Set of children
Set<Node> childrenOfParent = selectedNode.getChildren();
//create node to be added
newNode.setChildren(null);
newNode.setLabel(newNodeName);
newNode.setParent(selectedNode);
//add new node to selectedNode
childrenOfParent.add(newNode);
//saving selected node saves selectedNode as well as newNode
nodeDao.save(selectedNode);
//rebuild tree
tree.buildTreeModel();
}
The node: (more of the same from last time)
import javax.persistence.*;
import java.util.List;
import org.hibernate.annotations.GenericGenerator;
@Entity
@GenericGenerator(
name = "hibernate-uuid", strategy = "uuid"
)
public class Node {
@Id
@GeneratedValue(generator = "hibernate-uuid")
private String id;
@Column(nullable = false)
private String label;
@OneToMany(mappedBy = "parent", cascade = {CascadeType.ALL})
private List children;
@ManyToOne
@JoinColumn(name = "fk_parent_id")
private Node parent;
// Getters and Setters...
}
I think is a much more straight forward way of creating a dynamic JSF tree. Using the IceFaces Sample Application is a good starting point. Adding the few snippets of code I've provided above should get you the rest of the way.
10 Comments
Leave a comment
0 TrackBacks
Listed below are links to blogs that reference this entry: Dynamic Trees in JSF - The Easy Way.
TrackBack URL for this entry: http://www.nearinfinity.com/mt/mt-tb.cgi/422



I have problem by deleting the parent node. I have the same entity bean as you.
When I call remove method on the node, which has some children, I got SQLException:
The DELETE statement conflicted with the SAME TABLE REFERENCE constraint "FK2D4B8D9AABB5242". The conflict occurred in database "dxt-test", table "dbo.AuditCfgTreeItem", column 'fk_parent_id'.
What am I doing wrong?
Petra,
Look in your database and verify the name of the Node id column. If it's something other than "fk_parent_id", you will need to change the Node parent join column name. Also make sure the Node you are deleting isn't a parent of itself.
- Michael Bevels
Hi,
I have same kind of code,
When I expand/collapse my root node, the current page is getting reload which is causing slow in performance.
Its like I am displaying a table with 100+ rows on click of one tree node, when I collapse the root node, its resubmitting the screen, its like again its calling get data in datatable which is taking long time.
If there is no data in datatable it collapse/expand very fast. I need to stop the resubmit/reloading of the data table. Please need suggestion.
Thanks,
Reddy
I'm getting java.lang.IllegalStateException: Encountered a node [0:1:0] + with an illogical state. Node is expanded but it is also considered a leaf (a leaf cannot be considered expanded. when trying to delete last child of parent .
Will u pl show how to add the ice tree nodes from database and how on click of a ice table, how do we invoke another module
For me personally the remove of the parent node was problematic until I first came across the information about it at http://rapid4me.com and entered your post. I admire the way how easily you put the instructions here. Much appreciated. Thank you!
Hi Michael,
I am new to JSF. Thanks for your informative piece. Please could you recommend books and tutorial sites where I could learn more. Also, making available the source code for this piece would be greatly appreciated.
Thanks
Thanks for the article...
I'm getting java.lang.IllegalStateException: Encountered a node [0:1:0] + with an illogical state. Node is expanded but it is also considered a leaf (a leaf cannot be considered expanded. http://evildrome.com when trying to delete last child of parent .
For me personally the remove of the parent node was problematic until I first came across the information about it at http://rapidsharewire.com and entered your post. I admire the way how easily you put the instructions here. I appreciated. Thank you!