Wednesday, July 8, 2009

From JSF to Richfaces to Richfaces Portlet

We are going to start with a very simple JSF web application then convert that to a very simple Richfaces web application and then ultimately convert that Richfaces web application to Richfaces Portlet. This tutorial assumes that you have basic knowlege of JSF. All code used in this tutorial are at http://anonsvn.jboss.org/repos/qa/prabhat/. This application simply gives you some financial advice based on your age and your current savings. We all need some financial advice these days, don't we? ;-)

Converting a JSF application to Richfaces is a 3 step process:

1. Add Richfaces filter and some default parameters:

<!-- Plugging the "Blue Sky" skin into the project -->
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>blueSky</param-value>
</context-param>

<!-- Making the RichFaces skin spread to standard HTML controls -->
<context-param>
<param-name>org.richfaces.CONTROL_SKINNING</param-name>
<param-value>enable</param-value>
</context-param>
<filter>
<display-name>RichFaces Filter</display-name>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>

<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

2. Add Richfaces binaries to WEB-INF/lib:
You need three jars:

richfaces-api.jars
richfaces-ui.jar
richfaces-impl.jar

3. Add Richfaces components to your page:
You need to import two tag libraries. For a JSP page, you would need

<%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>

For an XHTMl page, you would need

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

Just doing these changes will make your page look pretty i.e. Rich.


From






To




Note:
1. If you deploy these app into JBoss AS, you do not need to bundle jsf jars in your war but you need them when deploying in tomcat.
2. Adding Richfaces config and binaries to an existing JSF project is very simple using JBoss Tools or JBDS. You simply add "Richfaces Capabilities".

Converting a Richfaces application to Richfaces Portlet

Since Portlets run on portal server, converting a web app to portlet is not that straightforward. I guess that's why there is no add "Portlet Capabilities" in JBoss Tools/JBDS. But it's equally easy to get started using Maven archetypes. Portlet based on JSF/Richfaces/Struts run on a portal server through portlet bridge. There is a separate project called JBoss Portlet Bridge which allows you to do that that for JSF/Richfaces/Seam based portlets. This project provides different maven archetypes to get you quickly started with these portlets. For richfaces based portlet, you would need to do


mvn archetype:generate -DarchetypeGroupId=org.jboss.portletbridge.archetypes -DarchetypeArtifactId=richfaces-basic -DarchetypeVersion=1.0.0.CR2 -DgroupId=org.jboss.test -DartifactId=richfaces-portlet -DarchetypeRepository=http://repository.jboss.org/maven2/

The archetype will create all required deployment descriptors portlet.xml,portlet-instances.xml, jboss-portlet.xml which you of course would need to update. We are going to import richfaces pages we created previously to this project and modify deployment descriptors accordingly. The important changes are portlet and portal server specific deployment descriptors and hooking up bridge with JSF.

1. Portlet Bridge's view handler and state manager on top of JSF/Richfaces
Modify faces-config.xml so that it has

<application>
<view-handler>org.jboss.portletbridge.application.PortletViewHandler</view-handler>
<state-manager>org.jboss.portletbridge.application.PortletStateManager</state-manager>
</application>

2. The Bridge Portlet to wrap xhtml as a view state of portlet

<portlet>
<portlet-name>SimpleRichfacesPortlet</portlet-name>
<portlet-class>javax.portlet.faces.GenericFacesPortlet</portlet-class>
<init-param>
<name>javax.portlet.faces.defaultViewId.view</name>
<value>/introduction.xhtml</value>
</init-param>
<init-param>
<name>javax.portlet.faces.preserveActionParams</name>
<value>true</value>
</init-param>
<expiration-cache>-0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Simple Richfaces Portlet</title>
</portlet-info>
</portlet>

We are configuring that GenericFacesPortlet is the portlet, it supports view mode and for default view, we are going to use introduction.xhtml that we created in JSF and Richfaces.

3. portlet-instances.xml does not change in this context i.e it's same as that of any java portlet

4. Inject needed Richfaces javascripts using jboss-portlet.xml

<portlet>
<portlet-name>SimpleRichfacesPortlet</portlet-name>
<header-content>
<script src="/faces/rfRes/org/ajax4jsf/framework.pack.js" type="text/javascript"></script>
<script src="/faces/rfRes/org/richfaces/ui.pack.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="/faces/rfRes/org/richfaces/skin.xcss">
</header-content>
</portlet>


This portlet when deployed to JBoss Portal looks like: