View Source

h1. Converting ICEfaces 1.8 Applications to ICEfaces 2 Tutorial

With the release of JSF 2 and ICEfaces 2, a common situation arises of porting and converting existing ICEfaces 1.8.x. This tutorial will demonstrate the required steps to convert a legacy application to "compat mode" in ICEfaces 2. This means you can still use your existing {{ice:}} components and backing beans, but aren't yet taking advantage of 2 specific features and benefits. The majority of the converting effort involves configuration files and libraries, so most of your page markup won't need to be significantly changed.

This tutorial assumes the reader has a basic understanding of JSF and ICEfaces, especially creating and working with projects related to those technologies. The focus is not to teach the foundations, but instead to learn about porting applications. More information about porting can also be found [here|ICEfaces 1.x Compatibility].

The goal of this tutorial is to examine a real world ICEfaces 1.8.x application. Once we have an understanding of the project we will begin the steps to port the application to ICEfaces 2. The application is a slightly modified version of the "jobApplication" used in the ICEfaces Online Training. There is a central form based page that can redirect to two pages based on different outcomes.
\\
\\
----
{panel}Here is the entire list of topics focused on throughout this tutorial:

# [jobApplication Introduction|#introold]
# [Step 1 - Add and Update Libraries|#step1]
#* [Step 1a - Remove Old Libraries|#step1a]
#* [Step 1b - Add Compat Jars|#step1b]
#* [Step 1c - Add JSF 2 Jars|#step1c]
# [Step 2 - Update faces-config.xml|#step2]
#* [Step 2a - Update Header|#step2a]
#* [Step 2b - Remove View Handler|#step2b]
#* [Step 2c - Change Bean Scopes|#step2c]
# [Step 3 - Update web.xml|#step3]
#* [Step 3a - Remove Old Servlets|#step3a]
#* [Step 3b - Add Resources Servlet|#step3b]
#* [Step 3c - Modify Faces Servlet|#step3c]
#* [Step 3d - Modify Context Parameters|#step3d]
# [Step 4 - Modify Page Markup|#step4]
#* [Step 4a - Modify index.jsp|#step4a]
#* [Step 4b - Modify applicantForm.xhtml|#step4b]
#* [Step 4c - Modify thankYou.xhtml and noThanks.xhtml|#step4c]
# [Step 5 - Build and Deploy the Application|#step5]

And available source code downloads:
* [jobApplication 1.8 Source Code|#olddownloads]
* [jobApplication 2 Source Code|#newdownloads]
{panel}
----
h3. Development Tools Used

The following tools were used to create the project.
* [Eclipse|http://www.eclipse.org/downloads/packages/release/galileo/sr2] IDE for Java EE Developers - Version Galileo
* [Tomcat 6.x|http://tomcat.apache.org/download-60.cgi] Web Server
* [Java 6.x|http://www.oracle.com/technetwork/java/javase/downloads/]
* [ICEfaces 1.8.2|http://www.icefaces.org/JForum/posts/list/14795.page] and [ICEfaces 2 Beta 2|http://www.icefaces.org/JForum/posts/list/17890.page]

h3. {anchor:olddownloads}jobApplication 1.8 Source Code

|| Example || Source || Notes ||
| jobApplication 1.8 project | [jobApplication 1.8 source code |Converting ICEfaces 1.8 Applications to ICEfaces 2^jobApplication-1.8.zip|Download Source Code] | The Eclipse workspace of the jobApplication project written in ICEfaces 1.8. |

h3. {anchor:introold}jobApplication Introduction

Download and extract the above source code bundle, and {{{_}Import \-> Existing Project into Workspace{_}}} the folder into your Eclipse instance. Build and deploy the application to your Tomcat instance, and navigate to the deployed jobApplication. You will see a page similar to the following:
!converting1.8-2.0-tutorial-old-screenshot.png!

Now let's examine the page code, to get a better idea of what the application is doing. There are three main pages:
* {{{*}applicantForm.xhtml{*}}}
** Main page that has a series of internationalized form fields with validation, partialSubmit, a ice:selectInputDate component, etc.
* {{{*}noThanks.xhtml{*}}}
** Basic page redirected to when the first name equals "John".
* {{{*}thankYou.xhtml{*}}}
** Similar page redirected to when the first name is anything else.

The Java code is fairly standard for 1.8, focusing on two beans:
* {{{*}bean.backing.ApplicantForm.java{*}}}
** Controller/backing bean for the {{applicantForm.xhtml}} page. This controls the submission and some of the rendering toggles on that page.
* {{{*}bean.model.Applicant.java{*}}}
** Model object containing variables for the different Applicant fields, like First Name and Travel Percentage. No UI specific functionality.
* *Supporting Beans*
** The {{ProvinceSupport.java}} and {{Province.java}} classes are used to back the available items in the ice:selectOneMenu found on the main page.

Other features:
* *Internationalization*
** The {{messages_en.properties}} and {{JSF-override_en.properties}} are used to internationalize the various form labels.

h3. {anchor:begin}Begin Converting the jobApplication

Now that we understand the project a bit better, we'll start the 1.8 to 2 conversion process. The steps below will help you understand the requirements of porting, and can be applied to any of your own projects.

h3. {anchor:step1}Step 1 - Add and Update Libraries

Currently jobApplicaiton is using ICEfaces 1.8.2 and JSF 1.2. We will want to upgrade these versions to 2.

h4. {anchor:step1a}Step 1a - Remove Old Libraries

First remove references in our project to ICEfaces 1.8.2 and JSF 1.2. This will likely require {{{_}Build Path{_}}} changes inside Eclipse. The ICEfaces Core, Facelets, and Support Libraries 1.8.2 should be removed, as should JSF 1.2 Sun RI. The exact naming may be different in your project.

h4. {anchor:step1b}Step 1b - Add Compat Jars

Download and extract the [ICEfaces 2 bundle|http://www.icefaces.org/main/downloads/], and copy the following jar files from {{icefaces/compat/lib/}} to {{jobApplication/WEB-INF/lib/}}:

* commons-beanutils.jar
* commons-collections.jar
* commons-digester.jar
* commons-logging.jar
* *icefaces-compat.jar*
* *icefaces.jar*
* _jstl.jar_
* jxl.jar
* krysalis-jCharts-1.0.0-alpha-1.jar

Note that {{{_}jstl.jar{_}}} is only required when running an ICEfaces compat application on Tomcat, which we are, so include it.

The primary jars are {{icefaces.jar}} and {{icefaces-compat.jar}}. The former contains all the ICEfaces 2 code we need, while the latter has compat specific code around {{ice:}} components.

h4. {anchor:step1c}Step 1c - Add JSF 2 Jars

Now we will add JSF 2. There are two jars we need to reference in {{icefaces/lib/}} called {{jsf-api.jar}} and {{jsf-impl.jar}}. The recommended approach is to create a custom {{{_}User Library{_}}} in your Eclipse project, but the jars could also be copied to the {{jobApplication/WEB-INF/lib/}} folder.

There will probably be a few errors within the project because of these changes. That's okay, we just need to modify the configuration and pages to be 2 specific to resolve this problem.

h3. {anchor:step2}Step 2 - Update {{faces-config.xml}}

Now we will change the XML configuration file {{faces-config.xml}}. The main changes will be scope related, to accomodate the new JSF 2 scopes.

h4. {anchor:step2a}Step 2a - Update Header

First we'll update the {{faces-config.xml}} header to be 2, instead of 1.2. Near the top of the file replace:

{code:title=Old faces-config.xml Header}<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
version="1.2">
{code}
With:

{code:title=New faces-config.xml Header}<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
{code}
As you can see we changed the version and schema location to 2.

h4. {anchor:step2b}Step 2b - Remove View Handler

Now we can remove the old reference to the D2DFaceletViewHandler, as this customization is handled transparently in ICEfaces 2. Remove the following line inside the {{<application>}} node:

{code:title=Old faces-config.xml View Handler}...
<view-handler>com.icesoft.faces.facelets.D2DFaceletViewHandler</view-handler>
...
{code}
h4. {anchor:step2c}Step 2c - Change Bean Scopes

Next we will modify the old {{<managed-bean-scope>}} nodes to conform to those available in ICEfaces 2. Previously ICEfaces 1.8.x used "extended request scope", which meant {{request}} was handled differently than it is now. The closest we can get to duplicating this functionality is using the new {{view}} scope.

Change all 3 beans to have a scope of view:

{code:title=Old faces-config.xml Bean Scope}...
<managed-bean-scope>request</managed-bean-scope>
...
{code}
Will become:

{code:title=New faces-config.xml Bean Scope}...
<managed-bean-scope>view</managed-bean-scope>
...
{code}
h3. {anchor:step3}Step 3 - Update {{web.xml}}

Now we will change the XML configuration file {{web.xml}}. The main change will be servlet mappings and adding some context parameters for ICEfaces 2.

h4. {anchor:step3a}Step 3a - Remove Old Servlets

The previously declared Persistent Faces Servlet and Blocking Servlet are no longer needed in ICEfaces 2, as their functionality has changed and setup has been reduced. Remove all declarations and mappings for those two servlets:

{code:title=Old web.xml ICEfaces Servlets} <servlet>
<servlet-name>Persistent Faces Servlet</servlet-name>
<servlet-class>com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Persistent Faces Servlet</servlet-name>
<url-pattern>*.iface</url-pattern>
<url-pattern>*.jspx</url-pattern>
<url-pattern>/xmlhttp/*</url-pattern>
<url-pattern>*.faces</url-pattern>
<url-pattern>*.jsf</url-pattern>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>Blocking Servlet</servlet-name>
<servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Blocking Servlet</servlet-name>
<url-pattern>/block/*</url-pattern>
</servlet-mapping>
{code}
h4. {anchor:step3b}Step 3b - Add Resources Servlet

As part of the compatibility requirements of porting a project, a new servlet will be added:

{code:title=New web.xml Resources Servlet} <servlet>
<servlet-name>Resource Servlet</servlet-name>
<servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Resource Servlet</servlet-name>
<url-pattern>/xmlhttp/*</url-pattern>
</servlet-mapping>
{code}
h4. {anchor:step3c}Step 3c - Modify Faces Servlet

The purpose of the FacesServlet has changed between 1.8 and 2, and so the declaration and mapping must as well. Replace the old declaration:

{code:title=Old web.xml Faces Servlet} <servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
{code}
With the new declaration and mapping:

{code:title=New web.xml Faces Servlet} <servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
{code}
h4. {anchor:step3d}Step 3d - Modify Context Parameters

The last change in {{web.xml}} is to change some of the {{context-param}} variables. Replace the old variables:

{code:title=Old web.xml Context Parameters} <context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>

<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
{code}
With a pair of new {{context-param}} variables that help ICEfaces 2 act more like 1.8.x in regards to markup and validation:

{code:title=New web.xml Context Parameters} <context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>

<context-param>
<param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
<param-value>false</param-value>
</context-param>
{code}
h3. {anchor:step4}Step 4 - Modify Page Markup

The final change is to modify the page markup to conform to ICEfaces 2 standards. These changes are mostly related to the header and format of the page, while all the {{ice:}} components can remain as they are.

h4. {anchor:step4a}Step 4a - Modify {{index.jsp}}

The first page to change is the simplest, and that is modifying that page {{index.jsp}} redirects to. Change the old redirect:

{code:title=Old index.jsp Redirect}...
response.sendRedirect("applicantForm.iface");
...
{code}
To point to the new mapping extension of the {{applicationForm}} page:

{code:title=New index.jsp Redirect}...
response.sendRedirect("applicantForm.jsf");
...
{code}
h4. {anchor:step4b}Step 4b - Modify {{applicantForm.xhtml}}

As mentioned the header, namespace, and body tags need to be modified to port 1.8 markup to ICEfaces 2. Replace the following tags near the top of the page:

{code:title=Old applicantForm.xhtml Code}...
<f:view xmlns:f="http://java.sun.com/jsf/core"
xmlns:ice="http://www.icesoft.com/icefaces/component">
<html>
<head>
<title>Job Application</title>
<ice:outputStyle href="./xmlhttp/css/xp/xp.css" />
</head>
<body>
...
{code}
With the following:

{code:title=New applicantForm.xhtml Code}<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ice="http://www.icesoft.com/icefaces/component">
<h:head>
<title>Job Application</title>
<ice:outputStyle href="./xmlhttp/css/xp/xp.css" />
</h:head>
<h:body>
{code}
Remember to replace all closing tags for the above changes.

This change was necessary because ICEfaces 2 uses {{html}} as the parent container tag of a page, instead of {{f:view}}. Also {{h:head}} and {{h:body}} are used instead of the old plain HTML {{head}} and {{body}}.

h4. {anchor:step4c}Step 4c - Modify {{thankYou.xhtml}} and {{noThanks.xhtml}}

Similary the headers of our other two pages will need to be changed. Replace the old header code in both pages:

{code:title=Old Header Code}<f:view xmlns:f="http://java.sun.com/jsf/core"
xmlns:ice="http://www.icesoft.com/icefaces/component">
<html>
<head><title>Thank You/No Thanks</title></head>
<body>
{code}
With a similar update:

{code:title=New Header Code}<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ice="http://www.icesoft.com/icefaces/component">
<h:head><title>No Thanks</title></h:head>
<h:body>
{code}
As before, remember to update the closing tags as well.

h3. {anchor:step5}Step 5 - Build and Deploy the Application

Those are all the changes we needed\! Overall porting 1.8 to ICEfaces 2 is fairly simple, and focuses more on configuration changes instead of being forced to modify your Java code or any functional markup.

Build and re-deploy the {{jobApplication}} and test it to ensure the functionality remains the same. From a user point of view the page will look the same, but now we're running on the modern ICEfaces 2\!

h3. {anchor:newdownloads}jobApplication 2 Source Code

The resulting code for the ICEfaces 2 version of the {{jobApplication}} is available if you need.

|| Example || Source || Notes ||
| jobApplication 2 project | [jobApplication 2 source code |Converting ICEfaces 1.8 Applications to ICEfaces 2^jobApplication-2.0.zip|Download Source Code] | The Eclipse workspace of the jobApplication project written in ICEfaces 2. |