How to migrate Richfaces Web applications to another Web UI

The Richfaces project has reached End of Life in 2016. Since then, it’s not being developed and no fixes are therefore provided. Richfaces it’s still used in many projects therefore we will learn in this guide which are the best option to pick up as an alternative framework.

Migrate Richfaces to JSF

If your project is heavily based on (or moving towards) Jakarta EE API, the best option to run a compliant Jakarta EE stack is to switch to to pure JSF 2.3 (Jakarta EE 8) or JSF 3 (Jakarta EE 9) stack.

Advantages: Over the last years several additions have been included in JSF. For example,  Facelets became a core part of the framework, allowing developers to create templates that could easily be applied to all views within an application.  Flows have been introduced, providing a means to carry state across a number specified views for more detailed session management.  Finally, changes have been made to allow components and views incorporate better client and server side interoperability via AJAX.

Also, consider that some peculiar features included in Richfaces (namely Advanced Bean Validation, Ajax Push Components) are now available also in JSF. Therefore you can migrate many features, once only available in Richfaces, to JSF.

Disadvantages: JSF features only a basic set of components which can wrap standard Form elements (buttons, text, labels, file upload). Therefore, if your application uses lots of widgets/components you cannot achieve an equivalent User Interface at the end of the migration.

Also, keep in mind that Richfaces still uses ManagedBeans as a glue between the Model and the View, have been. This has been deprecated since Java EE 8. Therefore, you have to replace Managed Beans with CDI Producers. For example, to fill up a Datatable:

@Produces
@Named
UserList userList;

@Produces
@Named
public List<UserList> getUserList() {
	return ejb.getListUsers();
}

And here is the view:

<h:form id="datatableform" >
<h:dataTable value="#{userList}" var="item" styleClass="table"
	headerClass="table-header"
	rowClasses="table-odd-row,table-even-row">
	<h:column>
		<f:facet name="header">Name</f:facet>
		<h:outputText value="#{item.name}" />
	</h:column>
	<h:column>
		<f:facet name="header">Surname</f:facet>
		<h:outputText value="#{item.surname}" />
	</h:column>

	<h:column>
		<f:facet name="header">Email</f:facet>
		<h:outputText value="#{item.email}" />
	</h:column>
	<h:column>
		<f:facet name="header">Delete</f:facet>
		<h:commandButton actionListener="#{manager.delete(item)}"
			styleClass="buttons" value="Delete" />
	</h:column>

</h:dataTable>

</h:form>

As you can see, CDI greatly simplifies data flow between the Controller and the View, however you have to include the cost of this migration too.

Migrate Richfaces to Primefaces

PrimeFaces is a popular open source framework which includes a full stack of components for JavaServer Faces (not exclusively).

You can learn more about Primefaces in this tutorial: PrimeFaces tutorial

Advantages: PrimeFaces is a mature solution since it’s been around for a while. It features a lightweight library with one jar, zero-configuration and no required dependencies. You just need to download PrimeFaces, add the primefaces-{version}.jar to your classpath and import the namespace to get started.

To migrate Richfaces applications to Primefaces you have to replace Richfaces libraries with a single Primefaces dependency:

<dependency>
    <groupId>org.primefaces</groupId>
    <artifactId>primefaces</artifactId>
    <version>10.0.0</version>
</dependency>

Then, you have to replace Richfaces namespaces with Primefaces’:

<html xmlns:p="http://primefaces.org/ui">
</html>

Finally, you have to replace Richfaces components with the equivalent Primefaces component. The following table can be used as a reference:

|            | RichFaces (change from)  | PrimeFaces (change to)       |
|------------|--------------------------|------------------------------|
|Listener    |a4j:actionListener        |f:setPropertyActionListener   |
|AJAX        |a4j:ajax                  |p:ajax                        |
|Button      |a4j:commandButton render  |p:commandButton update=       |
|Link        |a4j:commandLink           |p:commandLink                 |
|JS function |a4j:jsFunction            |p:remoteCommand               |
|Media output|a4j:mediaOutput           |p:graphicImage, ...           |
|Output area |a4j:outputPanel           |div or p:tab or p:outputPanel |
|Parameter   |a4j:param                 |f:param                       |
|Region      |a4j:region                |h:panelGroup or p:fragment    |
|Repeat      |a4j:repeat                |p:repeat                      |
|Status      |a4j:status                |p:ajaxStatus                  |
|Accordion   |rich:accordion            |p:accordionPanel              |
|Accord. item|rich:accordionItem        |p:tab                         |
|Autocomplete|rich:autocomplete         |p:autocomplete                |
|Calendar    |rich:calendar             |p:calendar                    |
|Sub-table   |rich:collapsibleSubTable  |p:dataTable (nested)          |
|Column      |rich:column               |p:column                      |
|Button      |rich:commandButton        |p:commandButton ajax="false"  |
|Command link|rich:commandLink          |p:commandLink ajax="false"    |
|Control     |rich:componentControl     |JS function                   |
|Data grid   |rich:dataGrid             |p:dataGrid                    |
|Data scroll |rich:dataScroller         |remove (use paginator)        |
|Data table  |rich:dataTable            |p:dataTable                   |
|Sub-menu    |rich:dropDownMenu         |p:submenu                     |
|Editor      |rich:editor               |p:editor(p:textEditor in PF 6)|
|File upload |rich:fileUpload           |p:fileUpload                  |
|Focus       |rich:focus                |p:focus                       |
|Google map  |rich:gmap (RF3)           |p:gmap                        |
|Hot key     |rich:hotKey               |p:hotkey                      |
|Spinner     |rich:inputNumberSpinner   |p:spinner                     |
|List        |rich:list                 |p:dataList                    |
|Menu item   |rich:menuItem             |p:menuitem                    |
|Message     |rich:message              |p:message                     |
|Messages    |rich:messages             |p:messages                    |
|Panel       |rich:panel                |p:panel                       |
|Panel menu  |rich:panelMenu            |p:panelMenu or p:menu         |
|Menu item   |rich:panelMenuItem        |p:menuitem                    |
|Pick list   |rich:pickList             |p:pickList                    |
|Popup       |rich:popup                |p:dialog                      |
|Select one  |rich:select               |p:selectOneMenu               |
|Tab         |rich:tab                  |p:tab                         |
|Menu bar    |rich:toolbar              |p:menubar or p:toolbar        |
|Menu group  |rich:toolbarGroup         |remove                        |
|Tooltip     |rich:tooltip              |p:tooltip                     |
|Tree        |rich:tree                 |p:tree                        |
|Tree node   |rich:treeNode             |p:treeNode                    |
|Label       |h:outputLabel             |p:outputLabel                 |
|Input text  |h:inputText               |p:inputText                   |
|Input secret|h:inputSecret             |p:password                    |
|Message     |h:message                 |p:message                     |
|Messages    |h:messages                |p:messages                    |
|Text area   |h:inputTextarea           |p:inputTextarea               |
|Dropdown    |h:selectOneListbox        |p:selectOneMenu               |
|Select one  |h:selectOneMenu           |p:selectOneMenu               |
|Multi-select|h:selectManyListbox       |p:selectManyMenu              |
|Check box   |h:selectBooleanCheckbox   |p:selectBooleanCheckbox       |
|Check boxes |h:selectManyCheckbox      |p:selectManyCheckbox          |
|Radio button|h:selectOneRadio          |p:selectOneRadio              |
|Button      |h:commandButton           |p:commandButton ajax="false   |
|Regular link|h:commandLink             |p:commandLink ajax="false"    |
|Image link  |h:commandLink             |p:menuitem                    |
|Link        |h:link                    |p:link                        |
|Column      |h:column                  |p:column                      |
|Repeat      |ui:repeat                 |p:repeat                      |
|Field set   |fieldset                  |p:fieldset                    |
|------------|--------------------------|------------------------------|

Disadvantages: Primefaces is the most advanced and widely used JSF framework. The migration from Richfaces is not instantaneous, however it has a well defined path. As usual, when dealing with frameworks with a lot of extra components/widgets the main disadvantage might be the vendor lock-in. The vendor lock-in is quite relevant for Primefaces for JSF as there aren’t (and probably won’t be) any other JSF framework you could migrate to your Primefaces application into.

At the cost of facing a higher migration cost, you might consider also some other spin offs from Primefaces which do have several potential alternatives (so less risk of vendor lock-in)

  • PrimeNG for Angular: a spin-off project from PrimeFaces, is a collection of open source rich UI components for Angular.
  • PrimeReact for React: a collection of rich UI components for React. PrimeReact is a sibling of the popular PrimeNG (Angular) and PrimeFaces (JSF) components suites.
  • PrimeVue for Vue.js: the new member of the Prime Family of Open Source UI components and shares the same DNA with PrimeFaces, PrimeNG, and PrimeReact.

Migrate Richfaces to a modern Javascript based framework

There are many options out there such as Angular JS or Vue.js just to name a few. A typical application which uses AngularJS as UI includes:

  • View: HTML pages including AngularJS directives
  • Controller: REST Endpoints coupled with EJB/CDI Beans for transactions
  • Model: Java Beans coupled with Entity beans.

As an example, check this tutorial: Develop a CRUD application using AngularJS and WildFly

Advantages: The main advantage of using a modern framework such as AngularJS is faster responsiveness and easier development and maintenance. Also, AngularJS is server side independent. Therefore you can replace it with an equivalent Javascript framework or simply expose the REST API to external services. Using this flexible stack allows a simpler integration with other systems and smooth test of your system.

Disadvantages: The application requires to be rewritten from the JSF-server side model to Java Script-client side model. This means the UI has to be rewritten completely or a large part of it. The REST Endpoints need to be inserted in-between the Services and the UI. Only the business functions might be preserved from migration, provided that you correctly separated the layers of your Richfaces application.

Found the article helpful? if so please follow us on Socials