To determine how well RF 3.3.x works under JSF 2.0 we have run automated test suites for richfaces-demo and components. This post describes environment setup, tests results and conclusions.
Part I. Setup.
First Alex Smirnov has created an application including some popular RF components (they are listed in RFPL-183).
This application is located here: https://svn.jboss.org/repos/richfaces/root/examples-sandbox/trunk/backwardCompatibility , another components can be added there easily if necessary.
After this we have setup the same configuration for Selenium testing applications:
- Changed dependencies from javax.faces 1.2.x to com.sun.faces 2.0.0-SNAPSHOT (NB: exclusions inside dependencies should not be touched!)
- Dependencies to Facelets updated to the latest available 1.1.15B1 version
- The following switch added to web.xml files of affected applications:
<context-param> <param-name>javax.faces.DISABLE_FACELET_JSF_VIEWHANDLER</param-name> <param-value>true</param-value> </context-param
That was enough to start running tests under JSF 2.0.
One more thing about setup - there are some build failures (either compilation errors and unit tests failures) due to JSF 2 API changes. I've described this in RFPL-204
Part II. Tests results
Tests were executed and there happened some failures. After sorting this out the following issues were detected:
There are problems with tests themselves
These issues are divided into two categories:
a) Tests that do not pass because of my local environment (russian system locale, Windows vs Linux, etc.). Status of these tests and components that they are covering is now unknown: RFPL-205
b) Changes in standard JSF 2.0 components renderers. Good examples of these are:
- checks for generated Faces messages (assertPresent/assertNotPresent now work incorrectly, JSF 2.0 always renders placeholder elemements for h:messages)
- h:dataTable now renders TD elements for empty cells, so again XPath count and assert(Not)Present checks are failing
As a solution I'd propose to create special compatibility layer, that will isolate such changes: RF-8026
There are problems with components
Just to note: by analysing results of testing, I was adding quick fixes for broken functionality to keep components working (fixes for bugs like RF-7971 completely breaking component's functionality; so some of the following problems could be introduced by these fixes).
The following issues were detected:
- RF-7971 - ""IllegalArgumentException: In AbstractTreeDataModel rowIndex must be -1" error in AbstractTreeDataModel.setRowIndex() when attempting to expand or collapse a tree node under JSF2"
- RF-8029 - "Seam conversations are not working for rich:dataTable"
- RF-8030 - "repeat: "binding" doesn't work for nested components"
- RF-8031 - "ExtendedDataTable: FilteringTestCase fails with exception for duplicate component ID"
- RF-8032 - "OrderingList and ListShuttle: user changes aren't processed by component"
- RF-8033 - Validator components do not work with Jetty and JSF 2.0
Test web application issues
- a4j:include test fails due to implicit navigation in JSF 2.0 - need to be reworked
- examples of customized table data models throw IllegalArgumentException for setRowIndex() method - this problem is tightly coupled with the resolution of aforementioned UIData issue. If the changes won't be isolated in RF components, users will have to upgrade their application code to get such models working correctly.
Part III. Conclusions
Three of six found issues are caused by the fact that base iteration components RF class UIDataAdaptor is not properly overriding visitTree(VisitContext context, VisitCallback callback) added in JSF 2.0.
From the architectural point of view this method is responsible for passing instance of special visitor class through child components or, for iteration components, it is responsible for passing instance of visitor through data model and children components.
It accepts new JSF 2 interfaces as arguments, so it is compile-time dependent on JSF 2.0 API. There's a functionality implemented using this method: state restoring, partial decoding, etc.
So basically we have several choices here:
1. Proper visitTree() implementation. That is the easiest solution for us, because we can add handling for this visit() method according to components functionality.
a. Two distributions of RF 3.3.x: JSF 1.2 and JSF 2.0
b. The same binaries for both JSF version. RF is compiled under JSF 2.0 and we rely on the dynamic imports resolution in JDK classloader for runtime
2. Without implementing visitTree() - we agree that compatibility with some standard features is not provided (like f:ajax partial decoding inside rich:tree) and just fix known issues that are already (or will be) found during testing
Point 1.b looks good, but need to test with different JVMs.
Ideally, changes should be isolated in a special richfaces-impl-jsf2. Alex also pointed to the fact that such isolation will probably make it possible for the same richfaces-impl-3.3.3-jsf2 to be used with older versions of richfaces-ui (e.g. 3.3.1.GA).
Current goal of this work is to let existing RF 3/JSF 1.2 applications to continue working with JSF 2.