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

Connection to Amazon Neptune endpoint from EKS during development

This small article will describe how to connect to Amazon Neptune database endpoint from your PC during development. Amazon Neptune is a fully managed graph database service from Amazon. Due to security reasons direct connections to Neptune are not allowed, so it's impossible to attach a public IP address or load balancer to that service. Instead access is restricted to the same VPC where Neptune is set up, so applications should be deployed in the same VPC to be able to access the database. That's a great idea for Production however it makes it very difficult to develop, debug and test applications locally. The instructions below will help you to create a tunnel towards Neptune endpoint considering you use Amazon EKS - a managed Kubernetes service from Amazon. As a side note, if you don't use EKS, the same idea of creating a tunnel can be implemented using a Bastion server . In Kubernetes we'll create a dedicated proxying pod. Prerequisites. Setting up a tunnel. ...

Managing Content Security Policy (CSP) in IBM MAS Manage

This article explores a new system property introduced in IBM MAS 8.11.0 and Manage 8.7.0+ that enhances security but can inadvertently break Google Maps functionality within Manage. We'll delve into the root cause, provide a step-by-step solution, and offer best practices for managing Content Security Policy (CSP) effectively. Understanding the issue IBM MAS 8.11.0 and Manage 8.7.0 introduced the mxe.sec.header.Content_Security_Policy   property, implementing CSP to safeguard against injection attacks. While beneficial, its default configuration restricts external resources, causing Google Maps and fonts to malfunction. CSP dictates which domains can serve various content types (scripts, images, fonts) to a web page. The default value in this property blocks Google-related domains by default. Original value font-src 'self' data: https://1.www.s81c.com *.walkme.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' ...