An Introduction To JBoss RichFaces
Join the DZone community and get the full member experience.
Join For FreeThis tutorial article will give a very quick introduction to JBoss RichFaces. Instead of just listing features, we are going to briefly define RichFaces and then dive right into an actual step-by-step example. In this example, we are going to go beyond the standard “Hello World” type of example. We will come back to this in just a moment.
JBoss RichFaces
If you know what RichFaces is already, then you can probably skip this section. For those of you who don't, here is what you need to know (the most important parts). JBoss RichFaces is a rich component library for JSF. RichFaces doesn't replace standard JSF, so you use RichFaces with either the Mojara JSF (Sun RI) implementation or the MyFaces implementation. RichFaces simply provides ready-to-use Ajax components to enable building Ajax-based applications. Another way to look at it is as just lots of extra JSF components beyond what the standard JSF provides. These components include all the necessary JavaScript coding, so you almost never have to work with JavaScript directly.
OK, this is the only place where I'm probably going to create some confusion, but I'm allowed to do it just once. RichFaces is not just a set of plug-ins, but actually a framework. One of its major features is its rich components. The components are divided into tag libraries. In addition, RichFaces provides a skinability (themes) features along with the Ajax4jsf CDK (Component Development Kit). For this article, I'm only mentioning CDK, so you are aware that it exists.
Two Tag Libraries
While the product is called RichFaces, it still has two different tag libraries. One tag library is called a4j: and the other is called rich:. The a4j: tag library provides page-level AJAX support. It basically provides foundation-like controls where you decide how to send a request, what to send to the server, and what to update. This approach gives you a lot of power and flexibility. The rich: tag library provides component-level AJAX support. Components from this library provide all their functionality out-of-the-box. In other words, you don’t need to decide how to send a request and what to update.
Skinability
Another major feature is skinability (or themes). Any number of skins (defined via a property file) can be created with different color schemes. When a particular skin is set, component renderers will refer to that skin and generate colors, images, styles, and stylesheets based on that skin. What this means is that you can easily change the look and feel of the whole application by simply switching to a different skin. I have dedicated a complete section to this topic.
We're done. That's all you need to know for now.
Beyond “Hello World”
I'm pretty sure you are somewhat tired of “Hello World” examples. While they are very useful (at the beginning), they are not very practical in the real world. So, this time, let's go beyond “Hello World.” In this example, we will display a list of users in a table. Each row will have an “Edit” button. When this button is clicked, the application will open up a modal panel where that selected user can be edited. When changes are saved, only that particular row in the table will be updated, not the entire table.
Let's get started. We will start with the required software. You might already have the required software, so it's really your choice if you want to use your existing setup or continue with my setup. Our final application will look like this:
[img_assist|nid=4698|title=|desc=|link=none|align=undefined|width=345|height=216]
[img_assist|nid=4699|title=|desc=|link=none|align=undefined|width=421|height=271]
Tutorial
Installation
We will start by downloading Eclipse.
Eclipse and WTP (Web Tools Project)
-
Create a new directory on the drive called richfaces. (Note the lack of spaces in the directory name.)
-
We will start by downloading Eclipse 3.3 and WebTools plug-ins. Go to the page http://www.eclipse.org/downloads/packages/release/europa/winter and select Eclipse IDE for Java EE Developers to download. This distribution already includes WTP (Web Tools Project plug-ins). Even if you have Eclipse, it makes sense to have a separate installation just for the example, so it won’t affect any of your other work.)
-
Unzip the downloaded file inside the richfaces directory you created.
Make sure you download the right Eclipse version and JBoss Tools version:
JBoss Tools version | Works with Eclipse version. |
JBoss Tools 2.1.x | Eclipse 3.3 (Europa) |
JBoss Tools
-
Download JBoss Tools by going to the page:http://labs.jboss.com/tools/download/ . Look for the latest 2.1.x GA version.
-
Click on the link labeled “All Plugins – Windows/Linux” and download the file.
-
Unzip the file inside the richfaces directory
At the end of these steps, you should have the following structure:
richfaces
eclipse
Don’t start Eclipse yet, we have one last step we need to complete: getting the project templates.
Project templates
Project templates will allow you to quickly create a project with RichFaces already configured.
-
Download this file:
-
Unzip the file and copy the content to
-
<eclipse>\plugins\org.jboss.tools.common.projecttemplates_X.X.X. You will be warned that you are overwriting some files, which you can safely do.
Tomcat
Download Tomcat 5.5 or 6.0 from http://tomcat.apache.org/ to the richfaces folder and unzip it.
At the end of these steps, you should have the following structure:
richfaces
eclipse
apache-tomcat-X.X.X
We are done with setup. Next, we are going to launch Eclipse and start building our application.
Application
Creating a new project
-
Select File/New/JSF Project
-
For the project name, enter “richfaces-start”
-
For JSF environment, select JSF 1.2, Facelets, RichFaces
-
For a template, select one based on the Tomcat version you are using
-
Click Finish to create the project
Creating the model class
As we are dealing with users, we are going to create a user model class.
In the JavaSource directory, create an example.model.User Java class and notice the package name:
package example.model; public class User { @Override public String toString() { return name + " " + email; } private String name; private String email; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public User(String name, String email) { super(); this.name = name; this.email = email; } }
The class is very simple. Our application will list one or more of these users. Next, we are going to create a managed bean. The managed bean will basically be a model for the user interface we will be building shortly.
Creating the managed bean
In JavaSource, create an example.beans.UserBean Java class. Again, pay attention to the package name:
package example.beans; import java.util.ArrayList; import java.util.List; import javax.annotation.PostConstruct; import example.model.User; public class UserBean { private List <User>users; public List <User>getUsers() { return users; } @PostConstruct public void init () { users = new ArrayList <User>(); users.add (new User("Joe", "joe@gmail.com")); users.add (new User("Charley", "charley@ymail.com")); users.add (new User("John", "john@hotmail.com")); users.add (new User("Greg", "greg@gmail.com")); users.add (new User("Prescila", "prescila@aol.com")); } }
This class is also simple. A list of five users is created and place inside an ArrayList. The @PostConstruct annotation is useful for initializing properties. It guarantees that the annotated method will only be called once when the bean is created.
To make this bean a managed bean, we need to register it in a JSF configuration file.
-
Open WebContent/WEB-INF/face-config.xml
-
Switch to the Tree view
-
Select Managed Beans and click Add...
- Keep the scope request
- For Class, enter the bean’s full Java class name, example.beans.UserBean
- For Name, enter or keep userBean -
Click Finish
We are ready to create the user interface.
Managed bean registration looks like this:
<managed-bean> <managed-bean-name>userBean</managed-bean-name> <managed-bean-class>example.beans.UserBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>
Creating user interface
In the WebContent folder, create a page called user.xhtml with the following content:
<!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" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j"> <head> <title>RichFaces</title> </head> <body> <h:form> <rich:panel> <f:facet name="header"> Just some users </f:facet> <rich:dataTable value="#{userBean.users}" var="user"> <h:column> <h:outputText id="name" value="#{user.name}"/> </h:column> <h:column> <h:outputText id="email" value="#{user.email}"/> </h:column> </rich:dataTable> </rich:panel> </h:form> </body> </html>
The page is also very simple. We just display all the users we created inside the managed bean using the rich:dataTable component. At this point we are ready to test the application.
Running on a server
1. Make sure everything is saved.
2. In Servers view, right click the server and select Start
3. Right click users.xhtml and select Run As/Run on Server
4. Click Finish
A Web browser window should open displaying users in a table.
[img_assist|nid=4744|title=|desc=|link=none|align=left|width=250|height=190]
The next step is to add a button to each column, which when clicked will open a modal panel with user details.
One thing you probably noticed is that you have a blue color schema while my screen shots have red color schema. I'm using a different skin. If you would like to change the skin, that's very easy to do. Open WEB-INF/web.xml file and change the skin parameter to ruby:
<context-param> <param-name>org.richfaces.SKIN</param-name> <param-value>ruby</param-value> </context-param>
Save and restart the server.
One thing that's still different is the font size.
Adding a modal panel
We will first create the modal panel. The modal panel has to be placed outside the original form, because it must have its own form:
<rich:modalPanel id="useredit"> <f:facet name="header"> User </f:facet> <h:form> <h:panelGrid id="userinfo"> <h:outputLabel for="nameInput" value="Name:"/> <h:inputText id="nameInput" value="#{userBean.selectedUser.name}"/> <h:outputLabel for="emailInput" value="Email:"/> <h:inputText id="emailInput" value="#{userBean.selectedUser.email}"/> <h:panelGrid columns="2"> <a href="#" onclick="#{rich:component('useredit')}.hide();return false"> Close </a> <a4j:commandLink oncomplete="#{rich:component('useredit')}.hide();return false"> Save </a4j:commandLink> </h:panelGrid> </h:panelGrid> </h:form> </rich:modalPanel>
The code is rather simple, I will talk about the Close and Save links shortly.
Next, we need to open the popup. To do that, we are going to add another column to the table. The column will contain a button to open the popup. We will make this column first. The coding looks like this:
... <h:column> <a4j:commandButton value="Edit" oncomplete="#{rich:component('useredit')}.show()" reRender="userinfo"> <f:setPropertyActionListener value="#{user}" target="#{userBean.selectedUser}" /> </a4j:commandButton> </h:column> ...
For both showing and hiding the modal panel, we use the RichFaces client-side function called #{rich:component('id')} to get a reference to the component (in our case, it’s the modal panel). Once we have a reference, we call the JavaScript API on that component. In our case, it is show() to open and hide() to close the modal panel. Later, we will be calling a save method when the Save button is clicked in the modal panel.
How do we know which row was selected which corresponds to the user we would like to edit. To accomplish that we use a standard JSF tag called f:setPropertyActionListener. It's basically a listener that will take the object in the current row and assign it to userBean.selectedUser property inside the managed bean. We don't yet have this property, so let's add it.
private User selectedUser; public User getSelectedUser() { return selectedUser; } public void setSelectedUser(User selectedUser) { this.selectedUser = selectedUser; }
Before we test this, there is one more thing to mention. Notice that the Edit button’s definition has a reRender attribute set to "userinfo". This is needed in order to rerender the selected user information. We first pass the selected user to the server. When the page is rendered back to the browser, we would like to rerender that property (userSelected) in order to display the selected user.
Go ahead and run the application as we did before. Before you run, make sure everything is saved and all the changes have been deployed. Your page should look like this:
[img_assist|nid=4699|title=|desc=|link=none|align=undefined|width=421|height=271]
We are now able to click on a particular row and display the user information in the modal panel. What we ultimately want to do is be able to edit user information, but only update the particular row for that user, instead of updating the whole table.
Specific row update
Updating the whole table is rather simple. How do we update only the row that has been edited? All data components in RichFaces (including a4j:repeat) come with a feature that allows updating only a subset of rows. All such components expose an ajaxKeys attribute that points to the row or rows that need to be updated.
Let's first go over the changes we need to make on the page.
First, we need to set the ajaxKeys attribute on rich:dataTable (changes shown in bold):
<rich:dataTable value="#{userBean.users}" var="user" ajaxKeys="#{userBean.rowsToUpdate}">
That's all we need to do with the table.
Next we need to call a save method from the modal panel when we make changes to the user information. The updated Save link will look like this:
<a4j:commandLink actionListener="#{userBean.save}" oncomplete="#{rich:component('useredit')}.hide()" reRender="name, email"> Save </a4j:commandLink>
The actionListener points to a listener inside the managed bean which we are going to create next. We also have the reRender attribute pointing to columns in the table. Basically, to achieve partial table update, we need to specify two things. First, which columns to update. In our case we are updating the name and email columns. Second, we need to specify which rows to update. This is done via the ajaxKeys attribute which is bound to a Set object that holds row numbers to update.
Let's see what changes are need in the managed bean.
First, we need to create the Set object to hold rows to update:
private Set <Integer>rowsToUpdate; public Set <Integer>getRowsToUpdate() { return rowsToUpdate; }
Only a getter is needed for this property as this property will never be set from the page.
Next, we need the save() listener.
public void save (ActionEvent event) { rowsToUpdate.clear(); rowsToUpdate.add(users.indexOf(selectedUser)); }
In the save listener, all we need is to save the row number of the user we are editing.
Finally, we need to initialize rowsToUpdate property inside the init() method, right after we create the users:
rowsToUpdate = new HashSet<Integer>();
The only other change we need is to add an a4j:keepAlive tag to the page. This is poor's man conversation scope (like in Seam). Basically, we need to keep the list of users alive for longer than a request and so a4j:keepAlive does just that. Right before the modal panel, add the following:
<a4j:keepAlive beanName="userBean"/>
Make sure everything is saved, redeploy, and run the application. You should now be able to open a modal panel, edit user information, and save the changes. When the changes are saved, only that particular row is updated.
Summary
I'm hoping this example showed you a little bit more than just Hello World. We have used a table component together with a modal panel. These are two components that very often used in real applications. I have also showed you how to edit a particular record inside a table via the modal panel and then only update that particular row. Of course, updating just a specific row is a feature of RichFaces data components.
To point out another thing, when we created an AJAX-based application here, we didn't have to deal with any JavaScript (well, besides the very simple client-side function available in RichFaces). RichFaces takes care of generating all the necessary (and usually quite complicated) JavaScript.
With RichFaces, you can continue using a JSF component-based approach, but with a large set of extra components to build applications with a rich user interface.
About the Author
Max Katz is a Senior Systems Engineer at Exadel. He has been helping customers jump-start their RIA development as well as providing mentoring, consulting, and training. Max is a recognized subject matter expert in the JSF developer community. He has provided JSF/RichFaces training for the past three years, presented at many conferences, and written several published articles on JSF-related topics. Max also leads Exadel's RIA strategy and writes about RIA technologies in his blog. He is an author of Practical RichFaces book (Apress). Max holds a BS in computer science from the University of California, Davis.
Opinions expressed by DZone contributors are their own.
Comments