36
JBoss RichFaces with Spring This article is going to show you how to build a RichFaces application with Spring. We are going to replace the standard JSF managed beans with Spring beans. We will first use an XML- based configuration approach and then switch to an annotations approach in Spring. (Note - The Project Template for this article can be downloaded here) If you want first to try RichFaces with standard JSF managed beans, no problem. Start with this article . To make it possible to create the application in just under an hour, we are not going to persist any data into a database. To keep things simple, we will keep the data in memory. Of course it's not very difficult to add a persistence layer to this application. Spring provides many tools to do that. Finally an article on how to use RichFaces with Spring Web Flow , is something that I'm saving for a future article. What Are We Going to Build? A pretty common request that I hear is how do you build a wizard in RichFaces. So, that's exactly what we are going to build. You come into a bar and on each table there is a screen via which you place an order. You click to start an order, a wizard is launched where you enter all the required information and place the order. We will also have the ability to view all placed orders. Additionally, we will be able to change the look and feel of the ordering screen using RichFaces’ skinnability feature. Note: All screen shots show a custom skin which you are going to create later.

JBoss RichFaces With Spring

Embed Size (px)

Citation preview

Page 1: JBoss RichFaces With Spring

JBoss RichFaces with SpringThis article is going to show you how to build a RichFaces application with Spring. We are going to replace the standard JSF managed beans with Spring beans. We will first use an XML-based configuration approach and then switch to an annotations approach in Spring.

(Note - The Project Template for this article can be downloaded here)If you want first to try RichFaces with standard JSF managed beans, no problem. Start with this article.

To make it possible to create the application in just under an hour, we are not going to persist any data into a database. To keep things simple, we will keep the data in memory. Of course it's not very difficult to add a persistence layer to this application. Spring provides many tools to do that.Finally an article on how to use RichFaces with Spring Web Flow, is something that I'm saving for a future article.

What Are We Going to Build?A pretty common request that I hear is how do you build a wizard in RichFaces. So, that's exactly what we are going to build. You come into a bar and on each table there is a screen via which you place an order. You click to start an order, a wizard is launched where you enter all the required information and place the order.  We will also have the ability to view all placed orders. Additionally, we will be able to change the look and feel of the ordering screen using RichFaces’ skinnability feature. 

Note: All screen shots show a custom skin which you are going to create later.

Page 2: JBoss RichFaces With Spring

 

Page 3: JBoss RichFaces With Spring

JBoss RichFacesJBoss RichFaces is a framework that consists of three main parts: AJAX (rich) enabled JSF components, skinnability, and CDK (Component Development Kit). RichFaces UI components are divided into two tag libraries a4j: and rich:. Both tag libraries offer out-of-the-box AJAX enabled JSF components. Skinnability enables you to skin a JSF application with default or custom skins (themes). Finally, the CDK is a facility for creating, generating and testing rich JSF components. 

RichFaces is not a JSF implementation. RichFaces UI components are just extra AJAX JSF components that work with any JSF implementation (1.1, 1.2, 2.0), any view technology (Facelets, JSP), and are integrated with 3rd party components (MyFaces, Tomahawk, Trinidad, etc).

Page 4: JBoss RichFaces With Spring

Installing RichFaces

Installing RichFaces is very easy.

Download

Download the latest RichFaces version from http://www.jboss.org/jbossrichfaces/ . 

Add three RichFaces JAR files to your application WEB-INF/lib directory:

richfaces-api-X.X.X.jar,

richfaces-impl-X.X.X.jar,

richfaces-ui-X.X.X.jar

RichFaces also depends on the following libraries: commons-beanutils.jar, commons-

collections.jar, commons-digester.jar, commons-logging.jar

As of the writing of this article, the latest RichFaces version is 3.3.0 . 

Note: to use Hibernate Validation, additional JAR files are needed. The JAR files are

included in the project. 

RichFaces Filter

Register the RichFaces filter in a web.xml file:view sourceprint?

01.<filter>02. <display-name>Ajax4jsf Filter</display-name>03. <filter-name>richfaces</filter-name>04. <filter-class>org.ajax4jsf.Filter</filter-class>05.</filter>06.<filter-mapping>07. <filter-name>richfaces</filter-name>08. <servlet-name>Faces Servlet</servlet-name>09. <dispatcher>REQUEST</dispatcher>10. <dispatcher>FORWARD</dispatcher>11. <dispatcher>INCLUDE</dispatcher>12.</filter-mapping>

 Skinning

Page 5: JBoss RichFaces With Spring

Optionally, to use one of the existing skins, add the following:view sourceprint?

1.<context-param>2. <param-name>org.richfaces.SKIN</param-name>3. <param-value>laguna</param-value>4.</context-param>

Note: new skins such as laguna, glassX and darkX are available in their own separate

JAR files.

Page Setup

If you are using Facelets, then add this to your page:

view sourceprint?

1.xmlns:a4j="http://richfaces.org/a4j"2.xmlns:rich="http://richfaces.org/rich"

Just in case you are still stuck with JSPs, you would then add this to your pages:

view sourceprint?

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

A little bit further in this article, I have created a ready-to-use Eclipse project with

RichFaces and Spring already configured. We are going to import the project into

Eclipse and then start development. In the “real” world, you would probably use Maven

2, but, to keep things simple and concentrate on RichFaces and Spring, we are going

to use a ready-made project.

SpringNot to repeat what has been said about Spring in numerous great articles and other

resources, I will not list every Spring feature. You can find numerous resources on the

Internet.  Simply stated, Spring is a framework that greatly simplifies enterprise Java

development. 

The part that's of interest to us here is Spring beans and injection of control (there's a great article on it here ). Spring is often a great candidate for a middle tier in a Web

application. While JSF offers us managed beans and basic dependency injection,

Spring's dependency injection is much more powerful. Why use two containers (JSF

and Spring) to manage beans when you can use just one? 

Page 6: JBoss RichFaces With Spring

As I mentioned at the beginning, I will show you two ways to configure Spring beans.

One is XML-based and the other is annotation-based. Even the XML-based

configuration significantly reduces the amount of XML you have to write compared to

the XML configuration of JSF managed beans

Page 7: JBoss RichFaces With Spring

Installing Spring

For the purpose of this example, Spring is installed and configured as follows. 

The following JAR files are added to the application:

spring-beans.jar

spring-context.jar

spring-core.jar

spring-web.jar

slf4-api-1.5.5.jar

slf4-simple-1.5.5.jar

Registering Spring in web.xml

Add the following to web.xml file:view sourceprint?

01.<context-param>02. <param-name>contextConfigLocation</param-name>03. <param-value>/WEB-INF/spring-beans.xml</param-value>04.</context-param>05.<listener>06. <listener class> org.springframework.web.context.ContextLoaderListener07. </listener-class>08.</listener>09.<listener>10. <listener-class>11. org.springframework.web.context.request.RequestContextListener12. </listener-class>13.</listener>

The contextConfigLocation parameter specifies a Spring beans configuration file

where Spring beans are going to be defined and managed. It looks (when almost

empty) like this:

view sourceprint?

Page 8: JBoss RichFaces With Spring

01.<?xml version="1.0" encoding="UTF-8"?>02.<beans xmlns="http://www.springframework.org/schema/beans"03.xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"04.xsi:schemaLocation="http://www.springframework.org/schema/beans05.http://www.springframework.org/schema/beans/spring-beans.xsd06.http://www.springframework.org/schema/context07.http://www.springframework.org/schema/context/spring-context-2.5.xsd">08. 09.<context:annotation-config />10.</beans>

We will be adding more stuff as we go. For now we only have <context:annotation-

config>. This tag enables support for Java EE 5 annotations such as @PostConstruct,

@PreDestory, and @Resource.

JSF Configuration File

As we are going to use Spring beans, we want Spring to resolve the beans and thus

need to register Spring's EL resolver in a JSF configuration file:view sourceprint?

1.<application>2. <el-resolver> org.springframework.web.jsf.el.SpringBeanFacesELResolver </el-res olver>3.</application>

That's all the configuration you need to use RichFaces and Spring. 

Page 9: JBoss RichFaces With Spring

Getting the ProjectI have used JBoss Tools to build the project.  You can of course use any tool of your

choice. Below I show steps for how to import the project as a JSF project into JBoss

Tools. You can also import the project as an existing Eclipse project. It's up to you. If

you need to install JBoss Tools, here is a [link]

1. Download this project

2. Import the project into Eclipse

         1. File/Import/Other

         2. Select JSF Project

         3. Point to web.xml file and follow the wizard steps. 

Before we continue, let's make sure that the project was deployed correctly and that

we can run it. Start the server by right-clicking Tomcat in the Servers view and

selecting Run. 

Right-click the project and select Run As\Run On Server. You should get this welcome

page.

 

Assembling the ApplicationCreating the Model

Let's start by creating the model for an order. In a real application, this object would

usually be an entity – an object that is saved and retrieved from a database. 

Page 10: JBoss RichFaces With Spring

The class is called Order and looks like this (note the package):view sourceprint ?

01.package bar.model;02. 03.public class Order {04. 05.private String name;06.private String email;07.private String drink;08.private String comments;09. 10.public Order(String name, String email, String drink, String comments) {11. super();12. this.name = name;13. this.email = email;14. this.drink = drink;15. this.comments = comments;16. 17. // getter and setters for each property18.}

Don't forget to generate getters and setters for each property. There is nothing

interesting about this object. 

Creating the Order Service

Next we are going to create a service class that knows how to add a new order. You

can place other methods into this service, such as finding and deleting orders. 

The OrderService class looks  like this:view sourceprint ?

01.package bar.service;02. 03.import java.util.ArrayList;04.import java.util.List;05.import javax.annotation.PostConstruct;06.import bar.model.Order;07. 08.public class OrderService {09. 10. private List <Order>orders;11. 12. public List<Order> getOrders() {

Page 11: JBoss RichFaces With Spring

13. return orders;14. }15. 16. public void addOrder (String name, String email, String drink,String comments){17. Order order = new Order(name, email, drink, comments);18. orders.add(order);19. }20. 21. @PostConstruct22. public void create (){23. orders = new ArrayList <Order> ();24. }25.}

A few things to note:

This service class will keep the list of all orders.

The addOrder method adds a new order to the list. The @PostConstruct annotation marks the create() method to be

invoked right after the OrderService class has been created. To be more technically correct, this method is called after all injections have been satisfied. While the class doesn't have dependencies, this method is still invoked and is a good place to initialize any properties.  In our case, we initialize the list object. 

Registering as a Spring Bean

We also need to register the Service bean with Spring. We want Spring to manage this

bean. Remember that we will first use XML to configure that. Registration looks like

this:view sourceprint ?

1.<bean id="service" class="bar.service.OrderService" scope="session" />

id is just the id or the name of this bean. 

We are placing this bean in session scope because we are keeping the list of all

orders in it. 

Page 12: JBoss RichFaces With Spring

We used the @PostConstruct annotation to initialized the list property. This is a

standard Java 5 annotation which is supported by Spring. 

Note: for @PostConstruct, @PreDestory and @Resource annotations to

work, the following has to be added to Spring configuration file:view sourceprint ?

1.<context:annotation-config/>

Alternatively , Spring also provides init-method attribute when registering the bean

as shown here:view sourceprint ?

1.<bean id="orderService" class="bar.service.Service" scope="session"  init-method="create"/>

This attribute points to a custom initialization method to invoke after setting bean

properties. 

A third option is to implement InitializingBean and DisposableBean interfaces:

[http://static.springframework.org/spring/docs/2.5.x/reference/beans.html].

Next we are going to create two view beans, one for the wizard and one for displaying

current orders.

Page 13: JBoss RichFaces With Spring

View BeansLet's start with BarBean class:view sourceprint ?

01.package bar.view;02. 03.import java.util.List;04.import bar.service.Service;05. 06.public class BarBean {07. 08. private OrderService orderService;09. 10. @SuppressWarnings("unchecked")11. public List getOrders () {12. return orderService.getOrders();13. }14. public int getRowCount () {15. return orderService.getOrders().size();16. }17. public Service getOrderService() {18. return orderService;19. }20. public void setOrderService(Service orderService) {21. this.orderService = orderService;22. }23.}

getOrders method calls the service class and returns all the orders. 

getRowCount will return the number of rows. It's used not to

render rich:dataTable component if the order is empty. 

The other question is how do we get an instance of orderService into this bean.

First, let's register this bean in Spring configuration file:view sourceprint ?

1.<bean id="barBean" class="bar.view.BarBean" scope="request"/>

We still have to deal with userService and how it gets initialized inside the bean.

This is were Spring DI   comes into play. We want Spring to inject userService into

the barBean, when barBean is being created. To accomplish that, we modify the

configuration to look like this:

Page 14: JBoss RichFaces With Spring

view sourceprint ?

1.<bean id="barBean" class="bar.view.BarBean" scope="request">2. <property name="orderService" >3. <ref bean="service" />4. </property>5.</bean>

service is the name under which we registered the Service class.

We are ready to look at WizardBean class. This class is the back end for the

wizard.view sourceprint ?

01.package bar.view;02. 03.import java.util.List;04.import javax.annotation.PostConstruct;05.import javax.faces.context.FacesContext;06.import javax.faces.event.ValueChangeEvent;07.import javax.faces.model.SelectItem;08.import org.hibernate.validator.Email;09.import org.hibernate.validator.NotEmpty;10.import org.hibernate.validator.Pattern;11.import bar.service.Service;12.import bar.utils.JSFUtils;13. 14.public class WizardBean implements java.io.Serializable {15. 16.private static final long serialVersionUID = 1L;17. 18.@NotEmpty(message = "Name must not be empty")19.@Pattern(regex = ".*[^\\s].*", message = "This string contain only spaces")20.private String name;21. 22.@NotEmpty23.@Email(message = "Invalid email format")24.private String email;25. 26.private String drink;27.private String comments;28.private String drinkCategorySelected;29. 30.private Service orderService;31. 32.private String startPage;33. 34.private List<SelectItem> drinkCategory;

Page 15: JBoss RichFaces With Spring

35.private List<SelectItem> drinkList;36. 37.// init all drinks38.private static final String [] CATEGORY = {"Brandy", "Rum", "Tequila","Whiskey", "Wine", "Beer"};39.private static final String [] BRANDY = {"XO", "VSOP", "VS"};40.private static final String [] RUM = {"Medium", "Full-bodied","Aromatic"};41.private static final String [] TEQUILA = {"Reposado", "Añejo","Blanco"};42.private static final String [] WHISKEY = {"Malt", "Grain", "Single Malt", };43.private static final String [] WINE = {"Red", "White", "Pink"};44.private static final String [] BEER = {"Ales", "Lager", "Specialty Beer", };45. 46.public void changeDrink(ValueChangeEvent event) {47.String newValue = (String) event.getNewValue();48. 49.if (newValue.equals("Brandy")) {drinkList = JSFUtils.createList(BRANDY); drink=BRANDY[0];}50.else if (newValue.equals("Rum")) {drinkList = JSFUtils.createList(RUM); drink=RUM[0];}51.else if (newValue.equals("Tequila")) {drinkList = JSFUtils.createList(TEQUILA);drink=TEQUILA[0];}52.else if (newValue.equals("Whiskey")) {drinkList = JSFUtils.createList(WHISKEY);drink=WHISKEY[0];}53.else if (newValue.equals("Wine")) {drinkList = JSFUtils.createList(WINE);drink=WINE[0];}54.else if (newValue.equals("Beer")) {drinkList = JSFUtils.createList(BEER);drink=BEER[0];}55.}56. [email protected] void create() {59.drinkCategorySelected = CATEGORY[0];60.drinkCategory = JSFUtils.createList(CATEGORY);61.drinkList = JSFUtils.createList(BRANDY);62.drink = BRANDY[0];63.}64.public void save() {65.orderService.addOrder(name, email, drink, comments);66.this.startPage = "/page1.xhtml";67. 

Page 16: JBoss RichFaces With Spring

68.FacesContext.getCurrentInstance().getExternalContext().getRequestMap()69..remove("wizardBean");70.}71. 72.}

Don't forget to generate setters and getters for each property. I have omitted them in

order to save space. 

It looks like a lot more happening in this class, but in reality not that much. First, there

are propeties such as email, name, drink and comments which correspond to different

wizard screens. If you notice, they also correspond to Order model class. 

email and name properties are annotated with Hibernate Validations annotations.

We will come back to them when we build the pages. 

The large section preceded by // init all drinks comment is how drinks list is

created. It's not the most pretty way, but it will do for this example. 

There is also JSF changeDrink value change listener. It will be invoked each time a

new drink category is selected and will load the drinks associated with that category. 

The save method saves the new order. The last line in save method removes the

bean from request scope. We will come back to it shortly. 

In this class as in BarBean, we have a reference to orderService. No where in

the class we instantiate the property. You probably guessed, but we are going to use

Spring's DI to inject the service into this bean.  Let's register this bean in Spring

configuratin file.

view sourceprint ?

1.<bean id="wizardBean" class="bar.view.WizardBean" scope="request">2. <property name="startPage" value="/page1.xhtml"/>3. <property name="orderService" >4. <ref bean="service" />5. </property>6.</bean>

Page 17: JBoss RichFaces With Spring

startPage property is initialized to the first page in the wizard. 

orderService is injected with service bean. 

One last class is the JSFUtils:view sourceprint ?

01.package bar.utils;02. 03.import java.util.ArrayList;04.import java.util.List;05. 06.import javax.faces.model.SelectItem;07. 08.public class JSFUtils {09. 10. public static List <SelectItem> createList (String [] data){11. ArrayList <SelectItem>list = new ArrayList <SelectItem>();12. for (String item : data){13. list.add (new SelectItem (item, item));14. }15. return list;16. }17.}

This only method in this class creates a list of SelectItem's. We are ready to create

the views. 

Page 18: JBoss RichFaces With Spring

Creating Views

Let's start with the main view which has a button to launch the wizard as well as

display all current orders. 

start.xhtml:

view sourceprint?

01.<h:form>02. <!--  launch wizard button -->03. <rich:panel header="Welcome to RichBar">04. <a4j:commandButton  value="Click to start your order"05. oncomplete="#{rich:component('wizard')}.show()" />06. </rich:panel>07. <rich:editor rendered="false" />08.</h:form>09. 10.<!--  modal panel where the wizard is running -->11.<rich:modalPanel id="wizard" width="550" height="300">12. <f:facet name="header">Drink Order</f:facet>13. <f:facet name="controls">14. <a href="#" onclick="#{rich:component('wizard')}.hide()">X</a>15. </f:facet>16. 17. <h:panelGroup id="wizardInclude">18. <a4j:include viewId="#{wizardBean.startPage}" />19. </h:panelGroup>20. 21.</rich:modalPanel>22. 23.<!--  order table -->24.<a4j:outputPanel id="orders">25. <rich:dataTable value="#{barBean.orders}" var="order"26. rendered="#{barBean.rowCount>0}" rowKeyVar="row">27. <rich:column>

Page 19: JBoss RichFaces With Spring

28. <f:facet name="header">Order #</f:facet>29. <h:outputText value="#{row+1}" />30. </rich:column>31. <rich:column>32. <f:facet name="header">Name</f:facet>33. <h:outputText value="#{order.name}" />34. </rich:column>35. <rich:column>36. <f:facet name="header">Email</f:facet>37. <h:outputText value="#{order.email}" />38. </rich:column>39. <rich:column>40. <f:facet name="header">Drink</f:facet>41. <h:outputText value="#{order.drink}" />42. </rich:column>43. <rich:column>44. <f:facet name="header">Comments</f:facet>45. <h:outputText value="#{order.comments}" escape="false" />46. </rich:column>47. </rich:dataTable>48.</a4j:outputPanel>49.</body>

There are three main things here. 

At the very top of the page, we place a button to launch the wizard.

a4j:commandButton opens the modal panel by using a built-in RichFaces JavaScript

function rich:component('id') and invoking the show() method on the modal panel. 

Next we have the actual modal panel. Two facets define modal panel header and a

control to close the modal panel. To close the modal panel we use the hide()

JavaScript function on the modal panel. Next is a4j:include tag. The tag works similar

to Facelets ui:include but also allows to navigate within the included content. That's

what's going to give us wizard functionality. Remember that #{wizardBean.startPage}

is initialized to /page1.xhtml in Spring configuration file. 

The last portion is a rich:dataTable control that displays all current orders. The table is

not rendered if the list is empty. We have also defined rowKeyVar attribute which holds

the current row number. We use it as order number in the display. 

The next four pages are part of the wizard. 

Page 20: JBoss RichFaces With Spring

page1.xhtml

view sourceprint?

01.<h:form xmlns="http://www.w3.org/1999/xhtml"02.xmlns:ui="http://java.sun.com/jsf/facelets"03.xmlns:h="http://java.sun.com/jsf/html"04.xmlns:f="http://java.sun.com/jsf/core"05.xmlns:rich="http://richfaces.org/rich"06.xmlns:a4j="http://richfaces.org/a4j">07. 08.<a4j:keepAlive beanName="wizardBean" />09. <rich:panel>10. <h:panelGrid>11. <h:panelGroup>12. <h:outputLabel value="Email:" for="email" />13. <h:outputText value=" (We will email you your receipt!)"14.style="FONT-SIZE: small;" />15. </h:panelGroup>16. <h:panelGroup>17. <h:inputText id="email" value="#{wizardBean.email}">18. <rich:ajaxValidator event="onkeyup" />19. </h:inputText>20. <rich:message for="email" />21. </h:panelGroup>22. <a4j:commandButton value="Next" action="next" />23. </h:panelGrid>24. </rich:panel>25.</h:form>

Page 21: JBoss RichFaces With Spring

In the first page of the wizard, we are only asking for an email so we can send the

customer the receipt via email (just like in Apple stores). Notice that the page uses

rich:ajaxValidator to validate the email field. rich:ajaxValidator works against standard

Hibernate Validation set in the bean:

view sourceprint?

1.@NotEmpty2.@Email(message = "Invalid email format")3.private String email;

This eliminates having to register a validator with the component on the page. Another

benefit is thatrich:ajaxValidator skips the Process Validations and Update Model

phases. As we are only validating the field, we can slightly increase performance by

not executing those phases. Skipping those two phases is identical to

setting bypassUpdates="true" (see RichFaces developers guide for further

information).  

One last thing we need to cover is a4:keepAlive tag placed at the top of the page. If

you look atwizardBean registration in Spring configuration file, you will notice that

the scope of this bean is request. As you know, this bean is what backing up the

wizard screens. Now, as we move from wizard screen to wizard screen, the values

entered on the previous screen are somehow being remembered. They are being

remembered because on the last screen (summary.xhtml), we are shown all the

values entered. But the bean is in request scope which means that for every request a

new bean is created and if that's the case then the old value will be lost. So, how are

the values saved? 

That's exactly what a4j:keepAlive tag does. It stores the bean (wizardBean) with

the UI component tree. On postback, the UI component tree is restored and also

restores the bean placing it back intorequest scope. This is basically a page scope,

as long as we are staying on this page, the bean and its properties will be available to

us on postback. 

The way a4j:keepAlive works is that it adds the bean to current UI view root. The

following is important, even though we placed a4j:keepAlive in the first wizard

screen (page1.xhtml), technically, the bean will be added to main.xhtml UI view

root. That's also the reason we only had to place a4j:keepAlive on the first page

Page 22: JBoss RichFaces With Spring

without having it on other wizard screens. Again, by placinga4j:keepAlive in the

first included page (page1.xhtml), we really added the tag to main.xhtml view. 

Now, because we are always staying on the same page, the wizardBean will always

be there. This is the correct behavior as we are basically getting page scope.

However, we want to clear the wizardBean in order to launch it again and not have old

values populated. Thus, we have to programmatically end the page scope and restart

it on next wizard launch. That's exactly what the last line in save method does:view sourceprint?

1.public void save() {2. orderService.addOrder(name, email, drink, comments);3. 4. FacesContext.getCurrentInstance().getExternalContext(). getRequestMap()5.. remove("wizardBean");6.}

page2.xhtml

view sourceprint?

01.<h:form xmlns="http://www.w3.org/1999/xhtml"02. xmlns:ui="http://java.sun.com/jsf/facelets"03. xmlns:h="http://java.sun.com/jsf/html"04 xmlns:f="http://java.sun.com/jsf/core"05. xmlns:rich="http://richfaces.org/rich"06 .xmlns:a4j="http://richfaces.org/a4j">07.<rich:panel>08. <h:panelGrid>09. <h:outputLabel value="Name:" for="name" />10. <h:panelGroup>11. <h:inputText id="name" value="#{wizardBean.name}" >

Page 23: JBoss RichFaces With Spring

12. <rich:ajaxValidator event="onkeyup"/>13. </h:inputText>14. <rich:message for="name"/>15. </h:panelGroup>16. <h:panelGroup>17. <a4j:commandButton value="Previous" action="prev" />18. <a4j:commandButton value="Next" action="next" />19. </h:panelGroup>20. </h:panelGrid>21.</rich:panel>22.</h:form>

The second page in the wizard prompts to enter the name. We again use

rich:ajaxValidator to validate the name field with Hibernate Validation. Validation is

defined as follows:

view sourceprint?

1.@NotEmpty(message = "Name must not be empty")2.@Pattern(regex = ".*[^\\s].*", message = "This string contain only spaces")3.private String name;

 

Page 24: JBoss RichFaces With Spring

page3.xhtml

view sourceprint ?

01.<h:form xmlns="http://www.w3.org/1999/xhtml"02.xmlns:ui="http://java.sun.com/jsf/facelets"03.xmlns:h="http://java.sun.com/jsf/html"04.xmlns:f="http://java.sun.com/jsf/core"05.xmlns:rich="http://richfaces.org/rich"06.xmlns:a4j="http://richfaces.org/a4j">  07.<rich:panel>08. <h:panelGrid>09. <h:panelGrid columns="2">10 .<h:outputLabel value="Category:" for="want" />11. <rich:inplaceSelect id="want"  value="#{wizardBean.drinkCategorySelected}"12. valueChangeListener="#{wizardBean.changeDrink}">13. <f:selectItems value="#{wizardBean.drinkCategory}"/>14. <a4j:support event="onviewactivated"  ajaxSingle="true"reRender="drink"/>15. </rich:inplaceSelect>16. 17. <h:outputLabel value="Drink:" for="drink" />

Page 25: JBoss RichFaces With Spring

18. <rich:inplaceSelect id="drink" value="#{wizardBean.drink}" >19. <f:selectItems value="#{wizardBean.drinkList}"/>20. </rich:inplaceSelect>21. 22. </h:panelGrid>23. <h:panelGroup>24. <a4j:commandButton value="Previous" action="prev" />25. <a4j:commandButton value="Next" action="next" />26. </h:panelGroup>27. </h:panelGrid>28.</rich:panel>29.</h:form>

The third screen in the wizard uses two rich:inplaceSelect components. The first one

allows you to select a drink category. Once a category is selected, drinks that belong

to that category are loaded in the second select via AJAX. Value change

listener wizardBean.changeDrink is called and loads the drinks associated with

selected category. Using a4j:support tag we attached an onchange event to

rich:inplaceSelect UI component to be fired when value changes. When the event is

fired, an AJAX request is sent.  ajaxSingle="true" means we only want to process

that UI component on the server. Finally, reRender points to the second list we are

rendering back now with a list of drinks.

page4.xhtml

view source

Page 26: JBoss RichFaces With Spring

print ?

01.<h:form xmlns="http://www.w3.org/1999/xhtml"02.xmlns:ui="http://java.sun.com/jsf/facelets"03.xmlns:h="http://java.sun.com/jsf/html"04.xmlns:f="http://java.sun.com/jsf/core"05.xmlns:rich="http://richfaces.org/rich"06.xmlns:a4j="http://richfaces.org/a4j">07.<rich:panel>08. <h:panelGrid>09. <h:outputLabel value="Anything else?" for="comments" />10. <rich:editor id="comments" autoResize="true"11. value="#{wizardBean.comments}">12. </rich:editor>13. 14. <h:panelGroup>15. <a4j:commandButton value="Previous" action="prev" />16. <a4j:commandButton value="Next" action="next" />17. </h:panelGroup>18. </h:panelGrid>19.</rich:panel>20.</h:form>

This page uses one of the new UI components introduced in RichFaces 3.3.0 – a rich

editor. rich:editor is based on tinyMCE widget. Rich:editor can be configured in many

different ways, here we are using a very simple configuration. You can check out

another example here.

summary.xhtml

Page 27: JBoss RichFaces With Spring

view sourceprint ?

01.<h:form xmlns="http://www.w3.org/1999/xhtml"02.xmlns:ui="http://java.sun.com/jsf/facelets"03.xmlns:h="http://java.sun.com/jsf/html"04.xmlns:f="http://java.sun.com/jsf/core"05.xmlns:rich="http://richfaces.org/rich"06.xmlns:a4j="http://richfaces.org/a4j">07. 08.<rich:panel>09. <h:panelGrid columns="2">10. <f:facet name="header">Summary</f:facet>11. 12. <h:outputText value="Name" />13. <h:outputText value="#{wizardBean.name}" />14. 15. <h:outputText value="Email:" />16. <h:outputText value="#{wizardBean.email}" />17. 18. <h:outputText value="Drink ordered:" />19. <h:outputText value="#{wizardBean.drink}" />20. 21. 22. <h:outputText value="Comments:" />23. <h:outputText value="#{wizardBean.comments}" escape="false"/>24. 25. </h:panelGrid>26. <h:panelGrid columns="2">27. <a4j:commandButton value="Wait.. Go back" action="prev" />28. <a4j:commandButton value="Place Order"

Page 28: JBoss RichFaces With Spring

29. action="#{wizardBean.save}"30. oncomplete="#{rich:component('wizard')}.hide()"31. reRender="orders, wizard"/>32. </h:panelGrid>33.</rich:panel>34.</h:form>

The last page is just a summary page. If any corrections are needed, it's possible to

click the back button. The Place Order button is bound to a save method and once the

action is completed we close the modal panel and re render the table – to update the

orders.

Creating Navigation

We won't be able to navigation inside the wizard without defining navigation rules.

Navigation rules are defined in JSF configuration file and look like this:

view sourceprint ?

01.<navigation-rule>02. <from-view-id>/page1.xhtml</from-view-id>03. <navigation-case>04. <from-outcome>next</from-outcome>05. <to-view-id>/page2.xhtml</to-view-id>06. </navigation-case>07.</navigation-rule>

08.<navigation-rule>09. <from-view-id>/page2.xhtml</from-view-id>10. <navigation-case>11. <from-outcome>next</from-outcome>12. <to-view-id>/page3.xhtml</to-view-id>13. </navigation-case>14. <navigation-case>15. <from-outcome>prev</from-outcome>16. <to-view-id>/page1.xhtml</to-view-id>17. </navigation-case>18.</navigation-rule>

19.<navigation-rule>20. <from-view-id>/page3.xhtml</from-view-id>

Page 29: JBoss RichFaces With Spring

21. <navigation-case>22. <from-outcome>next</from-outcome>23. <to-view-id>/page4.xhtml</to-view-id>24. </navigation-case>25. <navigation-case>26. <from-outcome>prev</from-outcome>27. <to-view-id>/page2.xhtml</to-view-id>28. </navigation-case>29.</navigation-rule>

30.<navigation-rule>31. <from-view-id>/summary.xhtml</from-view-id>32. <navigation-case>33. <from-outcome>prev</from-outcome>34. <to-view-id>/page3.xhtml</to-view-id>35. </navigation-case>36.</navigation-rule>

37.<navigation-rule>38. <from-view-id>/page4.xhtml</from-view-id>39. <navigation-case>40. <from-outcome>next</from-outcome>41. <to-view-id>/summary.xhtml</to-view-id>42. </navigation-case>43. <navigation-case>44. <from-outcome>prev</from-outcome>45. <to-view-id>/page3.xhtml</to-view-id>46. </navigation-case>47.</navigation-rule>

Creating Custom Skins

If you open web.xml file, you will see the following entry that defines the current skin

used in the application:view sourceprint ?

1.<context-param>2. <param-name>org.richfaces.SKIN</param-name>

Page 30: JBoss RichFaces With Spring

3. <param-value>laguna</param-value>4.</context-param>

It's very easy to create a custom skin by changing just a few skin properties.

Skinnability is just an extension to CSS that allows to change the look and feel of

entire application by modifying a simple property file. 

Create a new property file in JavaSource root, call it laguna-largefont.skin.properties (all skins have to follow this naming convention):view sourceprint ?

1.baseSkin=laguna2.generalSizeFont=20px3.headerSizeFont=20px

All we are doing is using the existing laguna skin and overwriting just two properties.

Now just update skin in web.xml file:

view sourceprint ?

1.<context-param>2. <param-name>org.richfaces.SKIN</param-name>3. <param-value>laguna-largefont</param-value>4.</context-param>

Save, restart and run the application. 

At this point save everything and run the application. 

Learn how to change skins in runtime.

Switching to Spring Annotations

Using annotations instead off XML-base configurations is the fashionable thing in Java

enterprise development today.  On a more serious note, both approaches are needed.

I will leave it up to you to decide which to use and when. There are lots of resources

on the Internet the deal with that question. 

Using annotations does make it a little easier to develop the application you don't need

to worry about XML files which can grow rather large. In this last section, we are going

to use annotations instead of XML-based configuration. 

First, open WEB-INF/spring-beans.xml and add the following tag to support

annotations-based configuration:view sourceprint ?

1.<context:component-scan base-package="bar" />

Page 31: JBoss RichFaces With Spring

base-package is the package from which Spring container will start looking for

annotated classes. 

Next we should comment (or delete) the XML-based bean configuration:

view sourceprint ?

01.<!--02.<bean id="barBean" class="bar.view.BarBean" scope="request">03. <property name="orderService" >04. <ref bean="service" />05. </property>06.</bean>

07.<bean id="wizardBean" class="bar.view.WizardBean" scope="request">08. <property name="startPage" value="/page1.xhtml"/>09. <property name="orderService" >10. <ref bean="service" />11. </property>12.</bean>

13.<bean id="service" class="bar.service.Service" scope="session" />-->

Let's start with bar.service.Service bean:

We are going to annotate it as a Spring component:view sourceprint ?

1.@Service("orderService")2.@Scope ("session")3.public class OrderService {4....5.}

@Service is basically a specialization of @Component annotation and is better

suited to annotate components that perform service-layer

functionality.  @Scope annotation specified the scope into which this object will be

placed. If we didn't specify a scope, the default scope would be Singleton which means

there is just a once instance of this object in application which would also work in our

case. 

Page 32: JBoss RichFaces With Spring

Next we need to annotate barBean and wizardBean classes. Both have identical

annotations. Let's first start with BarBean. view sourceprint ?

1.@Component("barBean")2.@Scope("request")3.public class BarBean {4....5.}6. [email protected] OrderService orderService;

@Component registers the bean as a component with name specified in

parenthesis. One last thing is that we have to inject the service component into this

bean. This is done via @Autowiredannotation. The annotation will inject a

dependency based on type (@Qualified annotation can be used to to gain more

control in case Spring context contains more than one object of the expected type).   

Finally, WizardBean looks similar:view sourceprint ?

1.@Component("wizardBean")2.@Scope("request"3.public class WizardBean {4....5.}6. [email protected] OrderService orderService;

Well, we are done. Save and restart the server.

SummaryI'm hoping this example gave you a good idea of how to use RichFaces  with Spring.

While it can still be considered “introductory”, we covered some core concepts and

Page 33: JBoss RichFaces With Spring

features. If you are just starting with RichFaces, I suggest first to try this example which uses standard JSF managed beans and then move to this one. For

more RichFaces examples and tips, check out my blog

athttp://mkblog.exadel.com/