On April Google announced the support for Java on Google App Engine. I became aware of this last week and rushed to create an account and check it out. Since this is an ‘early look’ release, I had to wait until the guys at Google grant me the rights to use the service. Meanwhile I downloaded the SDK and started building a test application to check if the frameworks I mostly use are supported. My minimum requirements are JSF 1.2 with Facelets for templating (I also use ICEfaces but I can live without them). The results where positive while using the SDK on my computer but when I’ve uploaded the application on App Engine (my account was activated two days ago) I received a nasty error thrown during the initialization phase of JSF.
After hours of searching and debugging I finally managed to get it up and running. Now I’m going to list the steps involved. The most interesting and insightful resource I found is this post, which describes how to setup JSF on App Engine as a step in configuring JBoss Seam.
As the post author states, you’ll have to enable sessions in appengine-web.xml, then configure JSF as usually, then set it up to use JBoss’s EL implementation and finally use those patched classes in order to avoid API calls that are restricted by the security policy of App Engine. I only used the patched classes under ‘jboss-el’ and ‘jsf_mojarra’ since I don’t use Seam.
After this I added Facelets and gone through the necessary configuration steps, built the application and tried to run it on App Engine.
Problems Occurred (yes, of course, Murphy’s Law dictates it):
1) FacesServlet was not properly initialized. This is probably because App Engine does not initialize servlets at startup, instead initialization is postponed until the first request. As a result an IllegalStateException was thrown. To resolve the issue I had to add the following to web.xml:
<listener>
<listener-class>
com.sun.faces.config.ConfigureListener
</listener-class>
</listener>
Error Message:
javax.servlet.ServletException: java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
2) An error was thrown during FacesServlet initialization due to the use of a restricted class. After examining the stack trace I realized that JSF was trying to perform some XML validation and failed throwing a NoClassDefFoundError. I had no other option but to deactivate XML validation by setting the following at web.xml:
<context-param>
<param-name>com.sun.faces.validateXml</param-name>
<param-value>false</param-value>
</context-param>
Error Message:
java.lang.NoClassDefFoundError: 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.
3) EL API classes were missing, had to include the EL API class library to the project.
Error Message:
java.lang.ClassNotFoundException: javax.el.CompositeELResolver
One last upload of the application after all the above tweaks and voilĂ ! The homepage loaded without any errors! The fact is that I didn’t have time to perform any further tests and for sure I cannot tell if all the features of JSF and Facelets will work normally. I’m waiting for your feedback on this. Good Luck!
Posted in JavaServer Faces, Web Applications
So after you have made these changes have you seen any other problems? I am considering trying this out. Thanks for the info by the way!
Posted at June 29th, 2009 - 8:24 am