Wednesday, September 23, 2009

RichFaces Table with DataModel

Recently I needed to get the selected Row Object of my RichFaces Data Table in to a backing bean, so that I can further manipulate it.

Before that, I was using Array List to feed my Data Table. Somewhere on the way, I picked up that one can use the


import javax.faces.model.ArrayDataModel;
import javax.faces.model.DataModel;


from JSF. Let us say, that you have a Data Table, where you have a Data Object similar to this one:


public class DataObject{

private String fileName;
private String fileMime;
public DataObject(String fileName, String fileMime){
this.fileName=fileName;
this.fileMime=fileMime;
}
// getter and setter
// exist but are omitted for this example.
}


This Data Object can come from various sources, such as data base or services, or your business layer.

It is nice to have an icon displayed in the Data Table instead of the row Mime type, such as plain/text or something similar.

Let us assume, you have a set of application icons.

Now you write your data table in the XHTML File, and it looks similar to this:


















As you can see, the name of the file is taken directly from the table Data Model, while for the file type, we call a backing bean method to handle the mime type.

The real question is, how do we know which index of the array do we have at rendering time, so that we can calculate the image URL for the certain mime type.

The Backing bean would look similar to this:


public class MyBean{

private List dataModelList;
private DataModel dataModel;

public void init(){
// populate simple Array List
// with Data Objects.
dataModelList = new ArrayList();
dataModelList.add(new DataObject("first","plain/text"));
dataModelList.add(new DataObject("second","text/html"));

// fill the Data Model
dataModel = new ArrayDataModel(dataModelList);
}
/**
* The method that returns an string representation of
* of Image URL for the mime type of the file.
*/
public String getMimeIcon(){

if(null == dataModel){
return null;
}

if(dataModel.isRowAvailable()){
DataObject rowDataObject =
(DataObject) dataModel.getRowData();
return calculateMimeType(rowDataObject.getFileMime());
}
return null;
}
//getter and setter for the Data Model omitted here
// but exist in the real source.
}


As you can see, in the backing bean, the getter method getMimeIcon(); we look up if the data model row is available.

If so, the getRowData(); of the Data Model will return exactly the the Object for the row referenced by the Tag at iteration (render) time.

In this case, we can have as many mime typed object in the Data Model Object as we want. We can be certain of it, that each of them get their right mime type icon.

Tuesday, August 25, 2009

IPC issue in WebSphere 6.1

Inter Portlet Comunication (IPC) is the hot spot in Portal environment. I already had some experience with it and described it here: IPC with JSR 286.

Everyone would probably think as I thought, that this should work in WebSphere Portal 6.1.

And it does. BUT! There is one additional requirement for having this to work under WPS 6.1.

After deploying your Portlets in the WPS you will have to go to the Administration Tab of WPS.

Than on the left side click the Manage Pages.
In the newly opened page, you will see a Table with only one column. Click on ContentRoot.

After that you will have to find your own Page-Name, which corresponds to the the Tab-Name where you run your Portlets.

When done, on the far right you will see bunch of icons. Click pencil like icon (it also displays the name EDIT PAGE LAYOUT when going over with your mouse).

The Page Customizer will open. Four Tabs are available:

  • Content
  • Appearance
  • Locks
  • Wires

In the Content Tab, you add all the Portlets you want to run here on this page (your newly developed Portlets with IPC).

After doing, click the Wires Tab. WPS has already read your portlet.xml file. You will see a table with the following columns:

  • Source portlet - The Event Publishing Portlet
  • Sending - The Publishing Event name space and name
  • Target page - leave it as it is. Here you can define the Page if your target Portlet is on another page. If on the same page, leave it as it is.
  • Switch page - I don't really get it what this has to do with all of this here (but hey)
  • Target portlet - The Portlet that has to consume your Published Event
  • Receiving - The name space and name of your Published Event.
  • Wire Type - leave it to Public

Don't forget to press the tiny + button on the end. This has to be repeated for each IPC Event of your Portlets.

When done, press the Done Button.

Now you can go to your Page Tab and test your IPC Eventing.

Hope it works for you too.

Maven Dependency Management for running RichFaces project on WebSphere 6.1

It is somewhat troubling issue when trying to deploy the same project in different environments. Some Application Servers (AS) ship their own versions of different library's. This will cause the same application to fail or run on different AS. For example, JBoss ships the JSF Library's while WebSphere does not. Examples are numerous.

Here is how you can configure Maven to build your RichFaces Application with all the needed Jar's and up and running to WebSphere AS 6.1. - WebSphere Porta 6.1

NOTE: This might not work for another Server version!?





4.0.0
de.mycompany.group.id
myproject-artifact-id
war
Basic RichFaces on WebSphere
1.0
Basis RichFaces Project running on WebSphere 6.1



maven-compiler-plugin

1.5
1.5







apache-repo
apache-repo
http://myfaces.zones.apache.org/dist/maven-repository


ibiblio
ibiblio-repo
http://mirrors.ibiblio.org/pub/mirrors/maven


jboss-repository
jboss-maven
http://repository.jboss.org/maven2/



just-another-repository
maven-repo
http://mariner.volantis.com/maven



central
repository
http://repo1.maven.org/maven2


maven2-repository.dev.java.net
Java.net Repository for Maven
http://download.java.net/maven/2
default





codehaus-repository
Plugin Repository von Mojo Codehaus
http://repository.codehaus.org/







com.sun.facelets
jsf-facelets
1.1.14


javax.faces
jsf-impl
${jsf.version}


javax.faces
jsf-api
${jsf.version}


org.richfaces.ui
richfaces-ui
${richfaces.version}


org.ajax4jsf
ajax4jsf


javax.faces
jsf-api


javax.faces
jsf-impl




org.jboss.portletbridge
portletbridge-api
${portletbridge.version}


javax.faces
jsf-api


javax.faces
jsf-impl




org.jboss.portletbridge
portletbridge-impl
${portletbridge.version}


javax.faces
jsf-api


javax.faces
jsf-impl




spring
org.springframework
2.5.6



portlet-api
javax.portlet
2.0


commons-beanutils
commons-beanutils
1.8.0


commons-collections
commons-collections
3.2


commons-digester
commons-digester
1.8


commons-fileupload
commons-fileupload
1.2


commons-logging
commons-logging
1.1.1


logkit
logkit


avalon-framework
avalon-framework




commons-logging
commons-logging-api
1.1


commons-httpclient
commons-httpclient
3.0.1


javax.el
el-api
1.2


javax.el
el-ri
1.2


sun-jaxb
jaxb-api
2.1.9


sun-jaxb
jaxb-impl
2.1.9


apache-xerces
xercesImpl
2.9.1


cglib
cglib
2.1_3


asm
asm




asm
asm
1.5.3






commons-beanutils
commons-beanutils


commons-collections
commons-collections


commons-digester
commons-digester


commons-logging
commons-logging
provided


javax.faces
jsf-api


javax.faces
jsf-impl


javax.el
el-ri


javax.el
el-api


javax.portlet
portlet-api
provided


sun-jaxb
jaxb-api


sun-jaxb
jaxb-impl


cglib
cglib


asm
asm


apache-xerces
xercesImpl


commons-httpclient
commons-httpclient



org.jboss.portletbridge
portletbridge-api


org.jboss.portletbridge
portletbridge-impl



com.sun.facelets
jsf-facelets


org.richfaces.ui
richfaces-ui





1.2_12
3.3.1.GA
1.0.0.CR2




NOTE: Some of the dependencies might be included in the Dependency Management section, but not in the dependency. This is due to copy paste reasons. Just ignore, so will Maven do as well.

Wednesday, July 29, 2009

Maven Profile- Dynamic compilation for different target platforms

Have you ever had the case where you have one project that has to be deployed to different servers? You certainly know that different servers include different JAR files. You certainly know that the configuration files are not necessary the same. This can give you a lot of headache, it can also make you maintain two different project just cause the configuration.

Well I recently had similar problems. Had to maintain the same project that should be deployed to JBoss and WebSphere. To keep the long story short, Maven gave me the perfect opportunity to do this.

Let us assume that your Maven project looks similar to this:

+main-project
|
|--+ web-app-project
| |
| |-+src/main/java
| |-+src/main/webapp
| | |
| | +WEB-INF
| | |--+web.xml
| | |--+faces-config.xml
| |
| +pom.xml
+ pom.xml

As you may know the main-project pom.xml is where you keep your dependency management. In the dependency management you enter artifact id and group id of the JAR file you want to be inluded and it's version. Usually, you can define the scope of the JAR here. There are several of such scopes. The compile scope is default and means that your JAR will be included in your application. The other common scope is the provided scope. It tells maven, that this JAR should not be included in your final product, and the application will find it either on the server or it's runtime. This dependency management in your main pom.xml should look something like this:





javax.faces
jsf-impl
${jsf.version}






The dependency management tag will tell maven which JAR files and it's versions are needed in your project. But this won't make this Jars be yet included in your project. To indeed include them, you should put the same dependency's with out version between separate dependencies tag.

This you can do either in the main-project pom.xml or in the web-app-project pom.xml. I would suggest the later one, which will make Maven put those Jars under the WEB-INF/lib folder.

Your web-app-project pom.xml could than include those dependencies as follow:




javax.faces
jsf-impl





Notice that the dependency management tag is missing in this part of the configuration.

I must admit that this is little error prone code, but if you keep it nice and clear, it will allow you to manage your dependencies very easy, and if you store your project in a SVN Repository, you will have no need to store the Jar files into the repository.

Thus far, we have gone through basic maven configuration. You certainly are interested how all those Jar files can be managed for different servers.

The answer is maven profiles. Every maven profile needs unique profile id. Let's start with the maven command line that will call certain profile.

mvn -Pprofileid clean install
The accent is set to the parameter -P followed with the profile id. It is important to understand that there is no space between the parameter and the id. If you execute this maven command at this point having the above configuration, the profile will be ignored and the project will be compiled normally.

To add a profile for certain project, you can do this in your web-app-project pom.xml as follows:




websphere



This defines the new profile with id websphere. It can be called as follows:
mvn -Pwebsphere clean install
As you correctly assumed this is a empty profile, thus won't do any difference. But before we go on and add our WebSphere dependencies, remove the previous dependencies we added above. Now adding the WebSphere dependencies is only a trivial task, and is done as follow:




websphere


javax.faces
jsf-impl







As you can see, no mysterious thing happened here. Actually, you can use about any of the normal maven tags inside profile.





...
...
...
...
...

...
...
...
...
...
...
...
...





You can see more here.

Now that we have managed the dependencies for WebSphere, we would also like to alter different configuration files at compile time. This files can be various XML files, such as web.xml or faces-config.xml. Why is this necessary will be shown on simple example on the web.xml file configuring the RichFaces for WebSphere and JBoss.

In WebSphere you configure the RichFaces mapping as follow:



richfaces
/*
REQUEST
FORWARD
INCLUDE
ERROR



In JBoss you don't configure the RichFaces filter through URL mapping, but through the Faces Servlet name, like this:


richfaces
Faces Servlet
REQUEST
FORWARD
INCLUDE
ERROR



As you see, this is very conflicting. While the WebSphere configuration will also work for JBoss, still you will need additional configuration, to get RichFaces running on WebSphere as follow:


richfaces
/faces/rfRes/*
REQUEST
FORWARD
INCLUDE
ERROR



So, the both mappings did not work for me on JBoss Portal, thus had problem to maintain the configuration of RichFaces for both servers in the same Project.
Luckily, Maven gives the opportunity to filter resources of all kind. Here we need to filter the web resources, thus can be done in few steps:
  1. In your web-app-project add new directory named conf
  2. In this directory you create new properties file named something like websphere.properties
  3. Add new property such as richfaces.servlet.name.mapping=
  4. Add another property such as richfaces.url.mapping=
    /*

Please notice that this properties are added in the websphere.properties file. To have JBoss profile filtering, you need another property file called for example jboss.properties. Inside this file, you have to define the same properties and assign them different values.
Also notice that the url mapping is not needed for WebSphere RichFaces configuration, thus the property is assigned no value, which will result in empty line in the web.xml file.

Now that we have this properties which define different patterns or configuration tags. As you assumed, this won't do anything. Now we will have to tell maven that he needs to take this property files and filter our web.xml. this is done as follow:




websphere



org.apache.maven.plugins
maven-war-plugin




${basedir}/src/main/webapp/WEB-INF

WEB-INF
true






${basedir}/src/conf/jboss-portal.properties




javax.faces
jsf-impl






Here we add new maven plug in for this profile to the standard build. This plug in is the maven war plug in which enables filtering of the WEB-INF content of an web app. With the directory tag, we tell the plug in which directory should be filtered and set the filtering on true.

In order to add the values assigned to the properties in the websphere.properties file in to the web.xml, the following changes are made in to the web.xml file:


richfaces
${richfaces.servlet.name.mapping}
${richfaces.url.mapping}
REQUEST
FORWARD
INCLUDE
ERROR


At compile time, the properties will be replaced with their values, so the out coming file will result in what you preconfigured in your websphere.properties file.

So that is all about it. One needs time to get around this, but once one understands it, it is easy and clean.
I hope this helps.

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.

Thursday, April 9, 2009

The facet thing

I have been looking for this in the Web my self, and could not find any real help.

Creating JSF components in dynamic way can bring you some troubles. Many JSF components, when using XHTML or JSP require Facets to render part of it's own body or content. Examples are Header of RichFaces panel or the like.

When creating dynamically a RichFaces panel for example, you will ran in to a problem if you want to create a header for your panel. To ilustrate this, let's look in to the way you create a RichFaces Panel when using the RichFaces tags:








As you may noticed, the problem one run on when creating this code in pure Java would be the Facet tag. If you look in to the JSF documentation, you will probably find the javax.faces.webapp.FacetTag which you might think of using it. But when creating a new instance of this class, you will certainly wonder how to use it, since this tag has nothing to do with JSF directly.
There is workaround for the following problem. Let us look in to the Java code on how to produce the same code from the above xml source:



HtmlPanel panel = (HtmlPanel)
FacesContext.getCurrentInstance().
getApplication().
createComponent(HtmlPanel.COMPONENT_TYPE);
HtmlOutputText text= (HtmlOutputText )
FacesContext.getCurrentInstance().
getApplication().
createComponent(HtmlOutputText .COMPONENT_TYPE);

text.setValue("My Header");

// now we will add the text to the panel's header

panel.getFacets().put("header",text);



As you see, that's all there it is to it. Every container component (correct me if I am wrong) in JSF has a Map of it's Facets. According to the JSF specification, the Facet (Tag) can contain only one UIComponent. So if you want more component's in your header, such as Text and Image at a time, you should wrap this components with one Html Panel Group instance and add it to your Facet Map.

Wednesday, April 1, 2009

Creating dynamic listener method binding

If you are JSF developer, you are most probably familiar with the following scenario:











The my bean instance should be created by the MyBean class which should include the following three methods:

public class MyBean{

public String action(){
// do something and return a string for the JSF navigation facility

return "navigateToPage2";
}

public void actionListener(ActionEvent event){

UIComponent component = event.getComponent();
// do something with or with out the component.
// the same view in JSF will be reloaded after
// this method returns.
}

public void valueChangeListener(ValueChangeEvent event){
UIComponent component = event.getComponent();
// do something with or with out the component.
// the same view in JSF will be reloaded after
// this method returns.
}
}


Sometimes, there are cases, where you have to do the binding for your self instead letting JSF bind your components with your listener methods via XML.

It these case, you should do, what JSF will do for you. From the JSF Context, you can get a handle to the Expression Language Factory or short referred as EL.

The expression language works similarly as the Reflection API of Sun Java SE. The main difference (at least for me) is that you can use the EL expression to bind your components to certain bean instances and methods.

To get a grip of the EL handle, you can use the following approach:


FacesContext ctx = FacesContext.getCurrentInstance();
Application app = ctx.getApplication();
ExpressionFactory el = app.getExpressionFactory();


Instead writing this code, you can use the inline call of the EL expression as follows:

ExpressionFactory el = FacesContext.getCurrentInstance().
getApplication().
getExpressionFactory();


In end effect, it is all the same for Java. It only saves you few lines of code.

Now that we have the grip of the handle for the EL, we can use it to create dynamic binding of component's and bean methods.

I will reproduce the same code from above with the command button and the text input. One should keep in mind that one can do this basically with every single JSF component.

public HtmlCommandButton createMyButton(){
HtmlCommandButton button = FacesContext.getCurrentInstance().getApplication().
createComponent(HtmlCommandButton.COMPONENT_TYPE );

//create the EL binding for the action method with return type String
MethodExpression action= FacesContext.getCurrentInstance().
getApplication().getExpressionFactory().
createMethodExpression(FacesContext.getCurrentInstance().getELContext(),
#{myBean.action}, String.class, new Class[]{});

//create the EL binding for the action listener method with return type void
// and argument of ActionEvent type
MethodExpression actionListener= FacesContext.getCurrentInstance().
getApplication().getExpressionFactory().
createMethodExpression(FacesContext.getCurrentInstance().getELContext(),
#{myBean.action}, null, new Class[]{ActionEvent.class});

//bind them to the button component.
button.setActionExpression(action);
// add the listener to the action
button.addActionListener(new MethodExpressionActionListener(actionListener));

return button;

}


What is important to notice, is that when creating the action method EL with return type String the createMethodExpression method of the EL factory takes four arguments:
  1. The faces context
  2. The String which represents the EL expression which should be used for binding
  3. The return type of String class
  4. The argument's of the method, which in this case are none to be passed.
The same goes for the creation of the action listener EL expression, where as the return type is set to null and the only argument passed is of type ActionEvent class.

The last thing to do is to save this method expressions expression in the map of the JSF component for later use. This goes only for the action method with return type of String. To add the EL expression for listener, you have to wrap the Method expression with the MethodExpressionActionListener class. In doing so, you add this expression to the component via UIComponent.addActionListener(ActionEvent); method.

The next thing to do is to create the text input component with it's value change listener binding.


public HtmlInputText createMyInput(){
HtmlInputText input = FacesContext.getCurrentInstance().getApplication().
createComponent(HtmlInputText.COMPONENT_TYPE );
// create the value change listener
MethodExpression valueChange=
FacesContext.getCurrentInstance().getApplication().getExpressionFactory().
createMethodExpression(FacesContext.getCurrentInstance().getELContext(),
#{myBean.valueChangeListener}, null, new Class[]{ValueChangeEvent.class});

//add the listener to the component
input.addValueChangeListener(new MethodExpressionValueChangeListener(valueChange));

}



As you can see, this procedure is the same as if you create action event. The only difference is the argument of the method,which is of type ValueChangeEvent class.

Tuesday, March 24, 2009

Create Spring beans dynamically

Spring XML declared beans can be wired building your business structure. The problem with this approach is that these beans are loaded on the start up, when the Spring Context is created, which does not leave much of playground to modify or change beans at run time. How ever Spring offers opportunity to load beans in the Spring context on run time when beans are needed, and populate them at need.
For doing this, we need the Spring Application context. For this to accomplish, one can declare one dedicated Spring context bean, which will implement the ApplicationContextAware and BeanFactoryPostProcessor interfaces. This should look something like this:


public class MyContextWrapper implements ApplicationContextAware,
BeanFactoryPostProcessor {

private ApplicationContext appContext;
private ConfigurableListableBeanFactory factory;

public void postProcessBeanFactory(ConfigurableListableBeanFactory factory)
throws BeansException {
this.factory = factory;
}
public void setApplicationContext(ApplicationContext c)
throws BeansException {
this.appContext = c;
}

//setters and getters

}



The postProcessBeanFactory will be executed after reading the configuration files of the spring context. Here one can do other configurations and bean loading, or save the factory for later use.
The Spring application context can be used for later dynamic bean retrieval or other purposes.

For this approach to work, one should let spring load this bean in to it's context by declaring the bean in the XML configuration file as follow:






Now this bean can be loaded in any other bean of the application via referencing it:








Now that we have the grip of the Spring context and it's factory, we can create beans dynamically. For this purpose, we can use the GenericBeanDefinition which allows to load bean definitions as follows:

BeanDefinitionRegistry registry = ((BeanDefinitionRegistry )factory);

GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyBeanClass.class);
beanDefinition.setLazyInit(false);
beanDefinition.setAbstract(false);
beanDefinition.setAutowireCandidate(true);
beanDefinition.setScope("session");

registry.registerBeanDefinition("dynamicBean",beanDefinition);


As one can see, this bean is created in the session scope and will be stored in the session of the user. The property auto wire candidate tells spring if dependency's of the bean such as setter's or getter's or constructor argument's should be handled automatically by Spring. The property lay init tells Spring if this bean should be instantiated when needed.

To get a handle of Spring bean, one can use the Spring application context as follows:

Object bean=
getApplicationContext().getBean("dynamicBean");
if(bean instanceof MyBeanClass){
MyBeanClass myBean = (MyBeanClass) bean;

// do with the bean what ever you have to do.
}


As you can see, the dynamic bean creation in Spring is no big deal.It is easy to use, an certainly handy in many situations.

Thursday, March 19, 2009

JSR 286 IPC with JSF

In case you are portlets developer, you know what JSR 286 is. It is the holy grail for the portlets which should enable the portlets to communicate with each others. At least you would think it is the holy grail, until you read the specs and look upon the Suns minimalistic examples.
It seems to me, this spec is out for it's own sake, and forwards the developers in the ice age of pure html, which is unthinkable for someone who has got used to API's such as JSF or Struts. Vendors as JBoss or ICEFaces have yet to deliver a bridge which will support JSR 286 with an AJAX push.

The sad news is that JSR 286 works only with out AJAX push, and you have to do some work around to get the grips of it in JSF Portal environment.

The first thing to do is to define the event you want to publish. This is done in the portlet.xml. There are three declaration there:
  1. One Global declaration of your event
  2. Supported publishing event for your pulbishing portlet
  3. Supported processing event for our consumer portlet


The global event declaration looks as follow:



x:EventName
java.lang.String



In the Publishing portlet, put the following:



x:EventName



And atlast, in the consumer portlet:



x:EventName


Now that you have configured your event that it is only a simple String, you should set it. This can be done in two way's:

  1. Either extend javax.portlet.faces.GenericFacesPortlet and override the

    public void processAction(ActionRequest request, ActionResponse);
  2. Or set the event in one of your Faces action methods.
If you prefer the first way, than you have to think that your to pass your full class name in the portlet.xml for portlet instantiation which would look like this:


org.mycomp.IPCPublisher



If you prefer the JSF action method way, than your portlet.xml will look as usual:

javax.portlet.faces.GenericFacesPortlet



In you decide to override the method of the GenericFacesPortlet, than you will set the event similar to this:


public void processAction(ActionRequest request, ActionResponse response)
throws PortletException,IOException {

QName qname = new QName("http://www.mycomp.com/myevent" , "EventName");
response.setEvent(qname, "Hallo IPC Communication.");
}


If you decide you would like to publish this event from inside of your JSF action method, you can do that as follow:

public void publishIPCEvent(ActionEvent event){
Object response = FacesContext.getCurrentInstance()
.getExternalContext()
.getResponse();

if(response instanceof ActionResponse){
ActionResponse aResponse = (ActionResponse)response;
QName qname = new QName("http://www.mycomp.com/myevent" , "EventName");
aResponse.setEvent(qname, "Hallo IPC Communication.");
}
}



This method will be called as usual in JSF:








What is left is to read out this event in the Consumer portlet.
You should extend the Generic Faces Portlet and override the processEvent method. By doing that, don't forget to put the class definition in the portlet.xml as follow:

org.mycomp.IPCConsumer

Override the method as follow:

public void processEvent(EventRequest request, EventResponse response) {
Event event = request.getEvent();
if(event.getName().equals("EventName")){
String ipc = event.getValue();
response.getPortletSession().setAttribute("ipc",ipc);
}
}


As you can see, I read out the event and compare it's name if it is my event I want to handle. Than I read it's value and set it in the portlet session as attribute.

To get this value inside of JSF, you should do something like this:

Object ipc = FacesContext.getCurrentInstance()
.getExternalContext().getSession(false)
.getAttribute("ipc);



Some say that one can annotate the certain method, which should be responsible for processing the event. This should look something like this:

@ProcessEvent(qname="{http://www.mycomp.com/myevent}EventName")
public void myEventProcessingMethod(EventRequest request, EventResponse response){
Event event = request.getEvent();
if(event.getName().equals("EventName")){
String ipc = event.getValue();
response.getPortletSession().setAttribute("ipc",ipc);
}
}



But this method annotation did not work for me inside of JSF. The same should work with java.util.HashMap instead of java.lang.String as well.

Anyways, this IPC approach is not that straightforward as some would like it to be, but it fullfils it's purpose.

Tuesday, March 17, 2009

Create your JSF componenst with out JSP or Facelets Tags

It is personal reference. Some love XML Syntax, some try to save them from the XML Jungle. JSF is a framework that allows you to create components dynamically. The JSF Tags are only option.

If you prefer to create your compnents without JSP or Facelets, and you don't want to envent the weel again, you can define your JSF Panel Grid in your JSP or Facelet as follow:





Define the bean in Spring config file as follow:





This bean holds a instance of the JSF HtmlPanelGrid which renders the JSF Panel Grid for you. The JSF components should be added to the Panel Grid with it's public method getChildren().add(Object o);. Here is the example:


package org.mypackage;

import javax.faces.application.Application;
import javax.faces.component.html.HtmlOutputText;
import javax.faces.component.html.HtmlPanelGrid;
import javax.faces.context.FacesContext;


public class MyBean {

private HtmlPanelGrid panelGrid;

public MyBean(){

}
public void init(){

Application application = FacesContext.getCurrentInstance().getApplication();
setPanelGrid((HtmlPanelGrid) application.createComponent(HtmlPanelGrid.COMPONENT_TYPE));

HtmlOutputText text = (HtmlOutputText) application.createComponent(HtmlOutputText.COMPONENT_TYPE);

text.setValue("Hallo JSF with out Tags.");

getPanelGrid().getChildren().add(text);

}
public void setPanelGrid(HtmlPanelGrid panelGrid) {
this.panelGrid = panelGrid;
}
public HtmlPanelGrid getPanelGrid() {
return panelGrid;
}

}

  1. In line 16 is the public method which will be ivoked by Spring after instantiation of the Bean.
  2. Line 18 gets an instance of the current application.
  3. On line 19 we create an instance of HtmlOutputText with the help of the method createComponent which takes String as argument. Every JSF Component defines public static field COMPONENT_TYPE which returns the type of the component to be created.
  4. On line 21 a instance of HtmlOutputText is created in the same way as the HtmlOutputText.
  5. In line 23 we set the value of the output text.
  6. In line 25 we set the output text component as child of the Panel Grid.
On the end of the day, when JSF try's to render the Panel Grid with the ID dynamic in the JSP or Facelets, the Property panelGrid of the backing bean will be called and our instance would be copied and rendered.

In this way, we can create whole views or parts of it, as if we program in pure Java.

Monday, March 16, 2009

Basic RichFaces Project with Spring

To create basic RichFaces enabled project, you can run the following maven command provided by JBoss.
mvn archetype:generate
-DarchetypeGroupId=org.jboss.portletbridge.archetypes
-DarchetypeArtifactId=richfaces-basic
-DarchetypeVersion=1.0.0.B6
-DgroupId=org.whatever.project
-DartifactId=myprojectname
-DarchetypeRepository=http://repository.jboss.org/maven2/
Make sure that you use the proper version of the Portlet Bridge of Jboss. Read more here
To enable Spring to manage your JSF Beans you should add this context arguments to your web.xml




org.springframework.web.context.ContextLoaderListener





org.springframework.web.context.request.RequestContextListener




This are the listeners which enables Spring to load it's context and create the beans, and to process Request from JSF to Spring and preserve the session.

Inside of faces-config.xml :



org.springframework.web.jsf.DelegatingVariableResolver




This delegates the JSF Variable resolver to look up for EL Expressions defined beans in Spring. In other words, it replaces the standard JSF EL resolver.

Now you would be able to define your JSF Beans in Spring as follows:



xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">







This bean can be used with your JSF Tag as usual:





In deed simple.

Here is the full web.xml:



xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">


javax.faces.STATE_SAVING_METHOD
server




javax.portlet.faces.renderPolicy
ALWAYS_DELEGATE



org.ajax4jsf.RESOURCE_URI_PREFIX
rfRes



org.richfaces.LoadStyleStrategy
NONE



org.richfaces.LoadScriptStrategy
NONE



org.ajax4jsf.COMPRESS_SCRIPT
true



org.richfaces.CONTROL_SKINNING
enable



contextConfigLocation
classpath:spring-context.xml



RichFaces Filter
richfaces
org.ajax4jsf.Filter



richfaces
Faces Servlet
REQUEST
FORWARD
INCLUDE



com.sun.faces.config.ConfigureListener



org.springframework.web.context.ContextLoaderListener



org.springframework.web.context.request.RequestContextListener





Faces Servlet
javax.faces.webapp.FacesServlet
1




Faces Servlet
/faces/*


Faces Servlet
*.jsf



FacesServlet
*.mk




10



Restrict access to JSP pages

Restrict access to JSP pages



With no roles defined, no access granted



BASIC




Sunday, March 15, 2009

Adding Spring to the project

Spring is generally highly rated for it's IoC capabilities. It gained it's popularity while developers had hard times with EJB 2.0 Specs.

Since Spring can be needed in more sub-project or modules, it is only reasonable to create a central place in your project to implement your Spring code. Create a Maven module as described in the revious post. It should look similar to this:


The Spring configuration files should be placed inside of the src/main/resources folder.

The main Spring configuration file is named applicationContext.xml by default. How ever this is not mandatory. You can name it hwat ever you like. I called it spring-context.xml.

If you are using the Sprng for web app or portlets, you can tell Spring where to find your custom configuration file with the following entry in your web.xml descriptor:


Now that you have the basic structure for your Spring, you should add the Module in to the main Project pom.xml :


and add it as dependency to be available in other projects:
Now that the Spring module is configured and available as dependency for other modules, you can bind it in other modules by adding the dependency in their pom.xml as follows:

As you can notice, the dependency in other modules pom.xml is added without the version tag. In this way, the versioning of the project dependency's is handled central in the main project pom.xml.

Saturday, March 14, 2009

Maven project architecture

Maven alows the developer to manage Enterprise projects in a modular way. This keep the project in order when it grows in time.

To create new Maven project, you can click File>New Project and select Maven Project



By selecting Next the following dialog will show up:



Click finish. What is important to note is the packaging of the project. It is set on POM.

Next, in the workspace will show the new project. You can than create new Folder and name it modules and underneath this folder you can create other folders that will include your modules or component projects. Your project should look similar to the following:


Clicking the pom.xml should produce the following code:


To create new Module Project, you should click File > New Project and select Maven Module


If your main project was not authomatically selected as parent Project, you should click Browse and select it from the work space. Click Next.


Click finish. The Project will appear in your work space and looks like this:


Close the project, and remove it from the work space. But make sure you don't delete it. Go on your hard disk, where your wrk space is, and copy the new created project in the folder of your main project. After this, it should look something like this:




All we have to do, is to tell maven where to find the new Module. If you open the main project pom.xml, you will notice that Eclipse added your module as follows:


Change the entry in to tag as follows:


The last but not the least is to add the module as a dependency in the main project, so that other sub project- modules can import it as dependency.


In your command console, navigate to the folder of your main project and execute the following maven command:
mvn -X clean install

If everything goes well, maven will end with the following message: