JavaServer Faces 2.0 and Google App Engine Compatibility Issues

Last Modified: December 30, 2011

This section discusses some of the problems you you will encounter when you try to use Sun Microsystem's Reference Implementation of the JavaServer Faces 2.0 framework on the Google AppEngine platform.

Current Issues

The following compatibility issues with the 2.0.6 release of Oracle's reference implementation of the JavaServer Faces 2.0 specification  and the 1.6.1 release of the Google App Engine platform.

Thread Use in the JavaServer Faces Reference Implementation

By default, Sun's reference implementation (RI) for the JavaServer Faces (JSF) framework uses threads.  When running under traditional Java runtime environments, this does not present a problem because threading is allowed.  Unfortunately, applications deployed on the Google AppEngine platform cannot start threads of their own.  This is enumerated in the "Threads" sub-topic of the "Sandbox" section of the "Java Servlet Environment" document published on Google's web site (shown below).

A Java application cannot create a new java.lang.ThreadGroup nor a new java.lang.Thread. These restrictions also apply to JRE classes that make use of threads. For example, an application cannot create a new java.util.concurrent.ThreadPoolExecutor, or a java.util.Timer. An application can perform operations against the current thread, such as Thread.currentThread().dumpStack().

Solution

The release notes for the JSF 2.0 reference implementation updated with the release of the second beta describes the "com.sun.faces.enableThreading" configuration parameter which, when set to false, tells the framework NOT to use threads.  Adding the following to an application's WEB-INF/web.xml configuration file will stop any attempts by the JSF framework to spawn additional threads.

<!-- Disable use of threading for single-threaded environments such as

     the Google AppEngine. -->

<context-param>

<param-name>com.sun.faces.enableThreading</param-name>
<param-value>false</param-value>
<description>
When enabled, the runtime initialization and default ResourceHandler 
implementation will use threads to perform their functions. Set this 
value to false if threads aren't desired (as in the case of running 
within the Google Application Engine).

Note that when this option is disabled, the ResourceHandler will not 
pick up new versions of resources when ProjectStage is development.
</description>

</context-param>


If the com.sun.faces.enableThreading context parameter is not set to false (or omitted completely from the web.xml configuration file) an application deployed on the Google AppEngine will display a number of different errors all caused by the JSF reference implementation's attempts to construct threads.

Resolved Issues

Setting the "ProjectStage" Context Parameter to Anything But "Development"

Resolved in Release: 1.6.1 (possibly earlier)

NOTE: I mention (possibly earlier) because I have not been as diligent in testing these compatibility issues with each release.  In updating the "Configuring JavaServer Faces 2.0 to run on the Google App Engine Using Eclipse" article to be compatible with the 1.6.1 release of Google's AppEngine platform, I added the javax.faces.PROJECT_STAGE context parameter with a value of "Development" and the template application deployed and ran successfully.

While the release notes for the JSF 2.0 reference implementation indicate that setting the com.sun.faces.enableThreading context parameter equal to false will cause the "...ResourceHandle [to] not pick up new versions of resources when the ProjectStage is development.", practical experience has proven otherwise.  When the javax.faces.PROJECT_STAGE context parameter is set equal to Development, the web application will fail to start and the logs available in the Google AppEngine console will contain the following error message.

com.sun.faces.config.ConfigurationException: CONFIGURATION FAILED! access denied (java.lang.RuntimePermission modifyThreadGroup)
For more details, please refer to the "Samples of Threading Issues" document.

Solution

While working with a pre-release version of the JSF 2.0 reference implementation, it is recommended that the javax.faces.PROJECT_STAGE context parameter be set to either or ProductionUnitTestSystemTest, or Extension.  For example, a web application  of an application deployed on the Google AppEngine with the following setting in the WEB-INF/web.xml configuration file will not have a problem.

<context-param>

<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>

</context-param>


This section describes items that have, in the past, been a problem when running JSF2 applications on the Google App Engine platform; however, they should no longer be a problem when using a modern version of the local development tools or the current server-side runtime.

BasisLibrary: Restricted Class Issue

Resolved in Release: 1.5.0

After configuring a web application to use the second beta of the JSF 2.0 reference implementation and deploying it to the Google AppEngine platform the application failed to start.  The log files access through the application's AppEngine console reported the following error:
com.sun.faces.config.ConfigurationException: CONFIGURATION FAILED! 
com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary is a restricted class. Please see the Google App
Engine developer's guide for more details.

comprehensive stack trace presented in the application's log is available.

Solution

One solution to this particular problem was to place copies of the serializer.jar and xalan.jar files from the 2.7.1 release of the Apache Xalan-J libraries into the web application's WEB-INF/lib directory.

Another solution is to ensure that the web application's WEB-INF/web.xml file explicitly sets the following parameters:
  • javax.faces.PROJECT_STAGE
  • com.sun.faces.enableMultiThreadedStartup
  • com.sun.el.ExpressionFactoryImpl

JSP 2.1 Issue

Resolved in Release: 1.4.2

The Google AppEngine for Java SDK supports the JavaServer Pages 2.1 API specification.  Unfortunately, there is a difference between the Geronimo API jar (geronimo-jsp_2.1_spec-1.0.1.jar) and the Jasper implementation jar (jasper-runtime-5.0.28.jar).  The Geronimo API jar supports the 2.1 API specificaion; however, the code contained in the implementation jar only supports the JavaServer Pages 2.0 API.  This is documented in the Google AppEngine Issue 1506.

This problem manifests itself by displaying a java.lang.AbstractMethodError exception (example) when the getJspApplicationContext method is invoked on the javax.servlet.jsp.JspFactory class.  This happens when the web application starts up.

Solution

Fortunately, the problem can be fixed by explicitly defining the default Expression Language (EL) Expression Factory should be used via the com.sun.faces.expressionFactory web application context parameter in the web.xml.

The example below uses the Unified Expression Language developed as a sub-project of the Glassfish project.  The API and Implementation binaries can be downloaded from https://uel.dev.java.net/download.html.  The el-api-1.1.jar and el-impl-1.1.jar files should be downloaded and placed in the WEB-INF/lib directory of your GAE project.

The following text should be added to the WEB-INF/web.xml file of your GAE project.

<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>

com.google.appengine.api.datastore.DatastoreTimeoutException

In the grand tradition of practicing what you preach, the Google AppEngine for Java leverages the Datastore (built atop BigTable) and Memcache frameworks for session persistence.  It seems that, over time, a small percentage of Datastore operations will fail.

When attempting to display a web page containing JSF input components, a "com.google.appengine.api.datastore.DatastoreTimeoutException" (sample stack trace) may be encountered by your web application.  Once this error page is encountered in your application, no other page will work until your session times out.

According to Don Schwartz of Google, the next release of the Google AppEngine for Java will include "improved retry and error handling logic" that are intended to lessen the likelihood of frameworks such as JSF, Struts, etc. encountering this problem.

Solution

This problem still manifested itself in version 1.2.6 of the AppEngine SDK. You can work around this problem by setting the following context parameter in your web.xml file.

<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>

There are costs and benefits to saving the view state in the client tier.  The "JavaServer Faces" forum on forums.sun.com has a thread that summarizes the difference between the client and server options for the javax.faces.STATE_SAVING_METHOD configuration parameter.  Essentially, with the client option, view information is stored as a Base64 encoded value in a hidden field on your web form with the name com.sun.faces.VIEW.  Mert Caliskan's weblog discusses the pros and cons of storing state on the client or server.