Tuesday, July 14, 2009

Porting RichFaces Portlets in WebSphere 6.1 Portal

This was painful week of trying to get the rich faces to get work in WebSphere Portal 6.1 running on the WebSphereAS 6.1. I used fully functional RichFaces 3.3.0.GA enabled Portlets (JSR 286) which work fine in JBoss Portal 2.7.1 with JBoss Bridge 1.0.0.CR2, JSF 1.2_12.

When deploying this Portlets on WPS, they got started, but running the Portlets always failed. The problem was closely related to RichFaces and it's filter and how the Mapping of the Resources URL was built.

The following Exception was trhrown:


Rendering View[/myportlet/view.xhtml]
javax.faces.FacesException: Resources framework is not initialised, check web.xml for Filter configuration
at org.ajax4jsf.resource.ResourceBuilderImpl.getWebXml(ResourceBuilderImpl.java:116)
at org.ajax4jsf.resource.ResourceBuilderImpl.getUri(ResourceBuilderImpl.java:323)
at org.jboss.portletbridge.richfaces.PortalResourceBuilder.getUri(PortalResourceBuilder.java:29)

In short it tells that the Filter resources are not properly installed in the web.xml.

I traced the org.ajax4jsf.resource.ResourceBuilderImpl.getWebXm method and on the place where this exception is thrown, it appears that the WebXml Object is null.

I read here that the Ajax4Jsf Filter is not running in WebSphere.

I started playing with the filter mapping in the web.xml. Depending on the Filter Mapping I used in the web.xml, I either get the Portlet to render the Standart JSF with out RichFaces components or I get the above message.

When the Portlet renders the Standard JSF, I looked in to the source code of the page and I see the rich faces panels etc. printed out to XML/JS but the components are not loaded or rendered.
I noticed that the Java Script links are possibly not loading, cause they look in my opinion not correct.
For example, in the Source code I could see:

which I tried to download this way:
http:// localhost:8080/wps/myappcontextpath/rfResorg/richfaces/renderkit/html/scripts/utils.js which always returned:

Error 404: SRVE0190E: File not found: /myappcontextpath/rfResorg/richfaces/renderkit/html/scripts/utils.js


I initially thought that the part:/rfResorg/ should be more like: /rfRes/org/ and the following bug in the jboss jira gave me additional thoughts on the URLs.

I still ain't clear if this was the root cause of the problem, but with additional configuration games, I actually got it to work.

This is how the AJAX4JSF Filter Configuration in the web.xml now looks:


richfaces
org.ajax4jsf.Filter


richfaces
/*
REQUEST
FORWARD
INCLUDE
ERROR


richfaces
/faces/rfRes/*
REQUEST
FORWARD
INCLUDE
ERROR




I added one General mapping for every URL and one to get the Resources through the Faces Servlet. Don't ask me why this works, to me it looks weird enough.

This is not the whole pie. Additionally to this, I had to add the following factory in the faces-config.xml:



org.jboss.portletbridge.context.FacesContextFactoryImpl



So that was it all about. I don't know if this might work on another configuration or even WebSphere Portal, but for now it works on mine.

One more important issue: set the Classloading policy as application classes loaded first. This will make sure that your classes in your WEB-INF/lib/* Directory will be loaded first.

This way, you can run JSF 1.2_12 on your WPS 6.1

Update:

It appears that this issue is caused due to a Class loading problems in WPS. According to some sources, WPS loads the Filters and Servlets with different class loaders. This results in an Exception when the Filter Mapping is configured as followed



Faces Servlet



In this case, only the ULR based mapping as shown above will do, since the Servlet instance is not known to the Filter instance.

Friday, May 29, 2009

RichFaces tree - dynamic update of tree model

The previous RidhFaces simple tree example allows you to render tree data which are output at one render time. But what if your tree data model is so large, so that you can't render it all at once. Instead you have to update your tree model at run time on user request?

Rich faces provides a listener called change expand listener. In case the user selects certain node in your tree, this listener will be called and here you can update your tree model. In the following section I will show how this is done. Let's first see how this listener is bound to a tree component:








Please notice that I left all other tree property's intentionally. As you can see, this property will call the assigned method where you can handle your tree model. Let us look into the method closely and see how we can update our tree model.


import org.richfaces.event.NodeExpandedEvent;

public class MyBackingBean{

/**
* The tree expand expand listener method.
*/
public void processExpansion(NodeExpandedEvent nodeExpandedEvent){
// get the source or the component who fired this event.
Object source = nodeExpandedEvent.getSource();
if (source instanceof HtmlTreeNode) {
// It should be a html tree node, if yes get
// the ui tree which contains this node.
UITree tree = ((HtmlTreeNode) source).getUITree();
// avoid null pointer exceptions even though not needed. but safety first ;-)
if (tree == null) {
return;
}
// get the row key i.e. id of the given node.
Object rowKey = tree.getRowKey();
// get the model node of this node.
TreeNode selectedTreeModelNode = tree.getModelTreeNode(rowKey);
if(null != selectedTreeModelNode){
// add the children nodes.
addChildrenNodes(selectedTreeModelNode);
}
}
}
/**
* Method for adding children nodes to a given tree model node.
*/
public void addChildrenNodes(TreeNode node){
//process your node somehow. For this example I add only one node.
TreeNodeImpl newNode = new TreeNodeImpl();
newNode.setData("My New Node");
newNode.setParent(node);
node.addChild("rowKey", newNode);
}
}


So every time user clicks the icon for expanding nodes, this listener will be called and the tree model will be updated. When the response will be rendered, the updated tree model will be rendered out, including your newly added node(s).

The same process can be done while the user selects particular node of the tree. When the user selects particular node, a RichFaces will look for queued Select node listeners to be called. Such listener can be registered is a Select Node Listener.







To queue select node listener to the tree, you can use the nodeSelectListener property. Than you can create new public listener method in your backing bean as follow:


import org.richfaces.event.NodeSelectedEvent;

public class MyBackingBean{

/**
* The select node listener method.
*/
public void selectNode(NodeSelectedEvent event){
// get the component that fired this event.
UIComponent component = event.getComponent();
if (component instanceof HtmlTree) {
// if a rich faces html tree (it is sometimes also a ui tree)
//get the row key of selected node.
Object rowKey = ((HtmlTree) component).getRowKey();
//pull the model tree node out of ther.
TreeNode selectedTreeModelNode = ((HtmlTree) component).getModelTreeNode(rowKey);
if(null != selectedTreeModelNode){
// add the children to the model.
addChildrenNodes(selectedTreeModelNode);
}
}
}
}


You should notice that the same method for adding children to the model is called as in previous example for expanding the node. Now that we covered how we can update our tree model, we could decide that after selecting a node and updating it's model we would like to expand the node. To do this, there are few way's. The safest and preferable way would be through the tree state saving property. Let's look into it closer:








In the backing bean, you should create new property called tree state. This should look something like this:



/**
* Getters and Setters added.
*/
public class MyBackingBean{

private org.richfaces.component.state.TreeState treeState;

public void setTreeState(org.richfaces.component.state.TreeState treeState) {
this.treeState = treeState;
}

public org.richfaces.component.state.TreeState getTreeState() {
return treeState;
}

}


Now that we added the Getters and Setters for this property, we could add this line to our select node listener method:



import org.richfaces.event.NodeSelectedEvent;

public class MyBackingBean{

public void selectNode(NodeSelectedEvent event) throws Exception {

// ... same as in the previous section
if(null != selectedTreeModelNode){
//.... as in previous section
// queue the node to be expanded.
getTreeState().expandNode((UITree) tree,
(TreeRowKey) rowKey);
}
}
}
}


The tree state instance will be consulted at render time of the tree. It contains map's where the state of the nodes is saved. Expanded nodes have own map where the row key's are queued for expanded rendering. The method expand node of the tree state class queue's the row key of the given node to be rendered as expanded.

As you see, RichFaces is very flexible and provides methods for dynamic extending of the tree structure, avoiding to render the whole content of the tree at the beginning.

Pity that they don't have good tutorials on their components.

Thursday, May 28, 2009

Richfaces Tree - simple case

RichFaces Tree basics

RichFaces framework is providing a convenient approach for rendering trees in a browser. Information on the RichFaces tree component are found here.

There are few steps to be taken, when implementing a tree. These are:

  1. Creating your tree model class, which will hold the data that should be rendered by the tree.
  2. You have to include the RichFaces tree tag in your form, weather JSP or XHTML.
  3. Bind your tree model class with the tree tag using the JSF Expression language.
This tree steps are not that unfamiliar to any JSF developer. So let's look closely to them.

Let us start with step one and discuss the model class. Good way to start coding your model class is to extend the org.richfaces.model.TreeNode Interface provided by RichFaces. This interface is implementing all important methods needed by the tree to render your data. Another convinient way of providing your model for a tree is to use the RichFaces implementation org.richfaces.model.TreeNodeImpl of the above mentioned interface.

This is really the basic and most likely all that one need for a simple RichFaces tree.

Let us examine how a tree can be implemented as a set of objects!?

As a entry point we need a root node. Each root node have this attributes:
  1. Root node has no parent.
  2. Root node has one or many children.
  3. Root node has a name and id.
  4. Root node must not have a name.
  5. Root node is also a folder.
So for construction our tree model , we need a root node. This can be done by instantiating the TreeNodeImpl class this way:



public class TreeModel {
private org.richfaces.model.TreeNodeImpl root;

// GETTER and SETTER

//Constructor
public TreeModel(){
root = new org.richfaces.model.TreeNodeImpl();
root.setParent(null);
root.setData("Name of my Root Node");
}

}


That ain't that hard, don't you think?
Now that we have the root node, we can fill it with it's content or children nodes this way:


public class TreeModel{

public List treeContent;
public void propagateTree(){

for(Iterator it = treeContent.iterator(); it.hasNext();){
TreeNodeImpl node = new TreeNodeImpl();
NameIdPair pair = (NameIdPair) it.next();
node.setData(pair.getName());
node.setParent(root);
root.addChild(pair.getId(),node);
}
}
}


The class NameIdPair is only a data object contain two fields, name and id and it's getter and setter methods. The data in the list can be retrieved from a data base or any content management system.

In this case, the root node will become will become one level nodes, dependent on how many entries were saved in the list.

Now that we have our simple model, we need a tree that will render it.

The following is convenient way how to use the tree tag:


rerender="selectedNode"
ajaxsubmitselection="true" switchtype="ajax"
treenodevar="TreeNodeVar"
value="#{treeDataProvider.rootNode}"
var="treeItem" ajaxkeys="#{null}"
nodeface="node">

iconleaf="/icons/folder.png" icon="/icons/folder.png">





As you can see, the tag is very simple. The following points are worth mentioning:
  1. The root node we propagated and filled with other nodes is bound to the value property of the tree. The tree tag will dynamically load the root node and will render it and it's content.
  2. RichFaces tree tag provides three operating modes of rendering: server, ajax, client. The most convenient way is the ajax mode, which will update the tree with ajax and let you select a node with the help of ajax. The client mode is only good for small trees as the one in our example. It will render the whole content with java script to your brower. If you choice is the server mode, you will have to find a way how to pos a request to the server, so that your selection or model update take place.