Skip to main content

Notes on upgrade to JSF 2.1, Servlet 3.0, Spring 4.0, RichFaces 4.3

This article is devoted to an upgrade of a common JSF Spring application. Time flies and there is already Java EE 7 platform out and widely used. It's sometimes said that Spring framework has become legacy with appearance of Java EE 6. But it's out of scope of this post. Here I'm going to provide notes about the minimal changes that I found required for the upgrade of the application from JSF 1.2 to 2.1, from JSTL 1.1.2 to 1.2, from Servlet 2.4 to 3.0, from Spring 3.1.3 to 4.0.5, from RichFaces 3.3.3 to 4.3.7. It must be mentioned that the latest final RichFaces release 4.3.7 depends on JSF 2.1, JSTL 1.2 and Servlet 3.0.1 that dictated those versions. This post should not be considered as comprehensive but rather showing how I did the upgrade. See the links for more details.
  1. Jetty & Tomcat.
  2. JSTL.
  3. JSF & Facelets.
  4. Servlet.
  5. Spring framework.
  6. RichFaces.
Jetty & Tomcat
First, I upgraded the application to run with the latest servlet container versions. For development I use maven jetty plugin that had to be upgraded in pom.xml from version 6:
<plugin>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>maven-jetty-plugin</artifactId>
  <version>6.1.26</version>
  <configuration>
    <connectors>
      <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
        <port>8080</port>
        <maxIdleTime>30000</maxIdleTime>
      </connector>
    </connectors>
    <contextPath>/${project.artifactId}</contextPath>
    <systemProperties>
      <systemProperty>
        <name>org.apache.cocoon.mode</name>
        <value>dev</value>
      </systemProperty>
    </systemProperties>
  </configuration>
</plugin>
to version 9:
<plugin>
  <groupId>org.eclipse.jetty</groupId>
  <artifactId>jetty-maven-plugin</artifactId>
  <version>9.2.1.v20140609</version>
  <configuration>
    <scanIntervalSeconds>10</scanIntervalSeconds>
    <webApp>
      <contextPath>/${project.artifactId}</contextPath>
    </webApp>
    <systemProperties>
      <systemProperty>
        <name>org.apache.cocoon.mode</name>
        <value>dev</value>
      </systemProperty>
    </systemProperties>
  </configuration>
</plugin>
Besides, I could safely remove the following listeners from web.xml as the corresponding issue was fixed in the latest versions of tomcat:
<listener>
  <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

<listener>
  <listener-class>com.sun.faces.application.WebappLifecycleListener</listener-class>
</listener>

JSTL
As JSTL 1.2 is a maintenance release and I used only c:set tag, I had nothing to do except updating pom.xml:
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>jstl</artifactId>
  <version>1.2</version>
</dependency>

JSF & Facelets
While you can find useful this extended JSF upgrade guide at stackoverflow, I'm going to show the changes I made below. First, I removed facelets dependency and updated jsf dependencies versions in pom.xml. Initially it was:
<dependency>
  <groupId>javax.faces</groupId>
  <artifactId>jsf-api</artifactId>
  <version>1.2_13</version>
</dependency>
<dependency>
  <groupId>javax.faces</groupId>
  <artifactId>jsf-impl</artifactId>
  <version>1.2_13</version>
</dependency>
<dependency>
  <groupId>com.sun.facelets</groupId>
  <artifactId>jsf-facelets</artifactId>
  <version>1.1.15</version>
</dependency>
As I use RichFaces, its latest version 4.3.7.Final provides richfaces-bom artifact with required JSF version specified as 2.1.28. Thus, I could simply omit version tags:
<dependency>
  <groupId>com.sun.faces</groupId>
  <artifactId>jsf-api</artifactId>
</dependency>
<dependency>
  <groupId>com.sun.faces</groupId>
  <artifactId>jsf-impl</artifactId>
</dependency>
Second, I updated faces-config.xml to comply JSF 2.1 spec. Initially it was:
<faces-config version="1.2" 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">
  <application>
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
    <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
    <!-- locale-config and resource-bundle here -->
  </application>

  <!-- converters here -->

  <navigation-rule>
    <!-- navigation-cases here -->
  </navigation-rule>
</faces-config>
I modified the root declaration, removed FaceletViewHandler, added from-view-id to fix validation issue and replaced converters with annotations. Well, actually I didn't use JSF @FacesConverter annotation but used Spring @Component instead. Similarly, all managed beans were annotated with @Controller before so I didn't have to add @ManagedBean annotations during the upgrade. Using Spring annotations is allowed as a replacement for both JSF 1.2 and 2.0 thanks to SpringBeanFacesELResolver. As a matter of fact, Spring and JSF 2 are heavily overlapping regarding the annotation support. Finally, this is the new version:
<faces-config version="2.1" 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_1.xsd">
  <application>
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
    <!-- locale-config and resource-bundle here -->
  </application>

  <navigation-rule>
    <from-view-id>*</from-view-id>
    <!-- navigation-cases here -->
  </navigation-rule>
</faces-config>
Third, I modified web.xml to get rid of Facelets 1.x related context-param tags. Initially it was:
<context-param>
  <param-name>facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE</param-name>
  <param-value>false</param-value>
</context-param>

<context-param>
  <param-name>facelets.LIBRARIES</param-name>
  <param-value>/WEB-INF/springsecurity.taglib.xml</param-value>
</context-param>
As you can see, I use Spring Security taglib there that should be still declared:
<context-param>
  <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
  <param-value>/WEB-INF/springsecurity.taglib.xml</param-value>
</context-param>
Fourth, the taglib springsecurity.taglib.xml should be modified as well. I won't paste the code here as the change just consists in renaming two Spring classes: Jsf12FaceletsAuthorizeTagHandler to FaceletsAuthorizeTagHandler and Jsf12FaceletsAuthorizeTagUtils to FaceletsAuthorizeTagUtils. You can find the final version of the taglib in spring samples here.
Finally, I replaced head with h:head and body with h:body in all xhtml files.

Servlet
To upgrade Servlet, first I updated pom.xml as usual. Initially it was:
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>servlet-api</artifactId>
  <version>2.5</version>
  <scope>provided</scope>
</dependency>
As I use RichFaces, the servlet version is already specified as 3.0.1 in its bom artifact. Thus, I can simply add the dependency without version tag:
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <scope>provided</scope>
</dependency>
Then I updated the root declaration of web.xml. Below you can see both versions:
<web-app 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-app_2_5.xsd"
         version="2.5">
<web-app 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-app_3_0.xsd"
         version="3.0">
Finally, as there is a custom listener in the application, I added @WebListener annotation to that class and removed the listener from web.xml.

Spring framework
As for the Spring framework upgrade, the changes were absolutely minimal in my case. First, I updated Spring versions in pom.xml including Security, Web Services and Web Flow dependencies. Initially it was:
<properties>
  <spring.version>3.1.3.RELEASE</spring.version>
  <spring.security.version>3.1.3.RELEASE</spring.security.version>
  <spring.ws.version>2.1.1.RELEASE</spring.ws.version>
  <spring.webflow.version>2.3.1.RELEASE</spring.webflow.version>
</properties>
The updated code is:
<properties>
  <spring.version>4.0.5.RELEASE</spring.version>
  <spring.security.version>3.2.4.RELEASE</spring.security.version>
  <spring.ws.version>2.2.0.RELEASE</spring.ws.version>
  <spring.webflow.version>2.4.0.RELEASE</spring.webflow.version>
</properties>
Second, it appeared wsdl4j:wsdl4j:1.6.1 artifact was required but missing after the upgrade so I added it to the dependencies.
Finally, I replaced versioned schema locations with non-versioned in root declarations of all Spring configuration files.

RichFaces
The upgrade of RichFaces from 3.3.3 to 4.3.7 appeared to be very troublesome as I had to fix many issues afterwards. The official migration guide helps but does not cover every detail. First, I updated pom.xml from:
<properties>
  <richfaces.version>3.3.3.Final</richfaces.version>
</properties>
<dependencies>
  <dependency>
    <groupId>org.richfaces.framework</groupId>
    <artifactId>richfaces-impl</artifactId>
    <version>${richfaces.version}</version>
  </dependency>
  <dependency>
    <groupId>org.richfaces.ui</groupId>
    <artifactId>richfaces-ui</artifactId>
    <version>${richfaces.version}</version>
  </dependency>
</dependencies>
to:
<properties>
  <richfaces.version>4.3.7.Final</richfaces.version>
</properties>
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.richfaces</groupId>
      <artifactId>richfaces-bom</artifactId>
      <version>${richfaces.version}</version>
      <scope>import</scope>
      <type>pom</type>
    </dependency>
  </dependencies>
</dependencyManagement>
<dependencies>
  <dependency>
    <groupId>org.richfaces.core</groupId>
    <artifactId>richfaces-core-impl</artifactId>
  </dependency>
  <dependency>
    <groupId>org.richfaces.ui</groupId>
    <artifactId>richfaces-components-ui</artifactId>
  </dependency>
</dependencies>
Second, I modified web.xml:
  • removed context-param with name org.ajax4jsf.VIEW_HANDLERS
  • removed RichFaces filter and corresponding filter-mapping
Third, there were many RichFaces component changes, so I did the following:
  • changed namespace from xmlns:rich="http://richfaces.ajax4jsf.org/rich" to xmlns:rich="http://richfaces.org/rich"
  • renamed rich:toolTip to rich:tooltip and removed attribute direction="top-right"
  • renamed rich:toolBar to rich:toolbar and rich:toolBarGroup to rich:toolbarGroup
  • renamed rich:modalPanel to rich:popupPanel
  • renamed attribute value to label of rich:menuItem
  • renamed attribute reRender to render
  • replaced attribute width="x" with style="width: x" on rich:dataTable and rich:column
  • replaced Richfaces.showModalPanel('x') with #{rich:component('x')}.show();
  • replaced Richfaces.hideModalPanel('x') with #{rich:component('x')}.hide();
  • replaced rich:componentControl[@event="onclick"] with attribute onclick on the target element
  • removed attribute selfSorted and changed attribute sortOrder to use enumeration values instead of literals

Comments

  1. Thank you for this useful post. I followed this steps and came across the problem which was caused by the version of the following dependency

    com/ocpsoft/prettyfaces-jsf12/3.3.3/prettyfaces-jsf12-3.3.3.jar

    when I replaced it with

    com/ocpsoft/prettyfaces-jsf2/3.3.3/prettyfaces-jsf2-3.3.3.jar

    for the second version of JSF, the problem has gone.
    Thank you

    ReplyDelete

Post a Comment

Popular posts from this blog

DynamicReports and Spring MVC integration

This is a tutorial on how to exploit DynamicReports reporting library in an existing Spring MVC based web application. It's a continuation to the previous post where DynamicReports has been chosen as the most appropriate solution to implement an export feature in a web application (for my specific use case). The complete code won't be provided here but only the essential code snippets together with usage remarks. Also I've widely used this tutorial that describes a similar problem for an alternative reporting library.
So let's turn to the implementation description and start with a short plan of this how-to:
Adding project dependencies.Implementing the Controller part of the MVC pattern.Modifying the View part of the MVC pattern.Modifying web.xml.Adding project dependencies
I used to apply Maven Project Builder throughout my Java applications, thus the dependencies will be provided in the Maven format.

Maven project pom.xml file:
net.sourceforge.dynamicreportsdynamicrepo…

Choosing Java reporting tool - part 2

I've provided a general overview of possible solutions to get a reporting/exporting functionality in the previous post. This is the second overview of alternatives based on JasperReports reporting engine.

Since the previous part I've done the following:
Implemented a simple report using both DynamicJasper and DynamicReports to compare them from technical side.Investigated JasperServer features and tried to implement a simple report for JasperServer instance (it appeared we already have a ready licensed installation of JasperServer that makes it unreasonable to install a fresh one).
First, the comparison results of Java libraries (DynamicJasper and DynamicReports):
Both libraries suffer from poor-quality or missing Java docs but they look a bit better in DynamicJasper.Taking into account the point 1, a developer has to use online documentation and to review the code. Here the code looks definitely nicer and more readable for DynamicReports. With respect t…

Do It Yourself Java Profiling

This article is a free translation of the Russian one that is a transcript of the Russian video lecture done by Roman Elizarov at the Application Developer Days 2011 conference.
The lecturer talked about profiling of Java applications without any standalone tools. Instead, it's suggested to use internal JVM features (i.e. threaddumps, java agents, bytecode manipulation) to implement profiling quickly and efficiently. Moreover, it can be applied on Production environments with minimal overhead. This concept is called DIY or "Do It Yourself". Below the lecture's text and slides begin.
Today I'm giving a lecture "Do It Yourself Java Profiling". It's based on the real life experience that was gained during more than 10 years of developing high-loaded finance applications that work with huge amounts of data, millions currency rate changes per second and thousands of online users. As a result, we have to deal with profiling. Application profiling is an i…