JSF 2.0 on Google App Engine
I recently had the opportunity to migrate a Java web app from Glassfish to Google App Engine. I decided to document my experience. Here it is.
The web app was a JSF 2.0 app that used Primefaces and JPA with MySQL. There were no EJB’s. I started by trying to confirm that all the parts were compatible with GAE. The first step was to get JSF 2.0 to run. I followed the instructions in JSF 2.0.2 and Google App Engine. I actually used the mojarra-2.0.3-FCS source archive which was current at the time. It goes a lot easier if you have Netbeans since the source archive is structured as a Netbeans maven project.
Primefaces is largely based on jQuery and YUI and I only noticed a couple of issues. The only problems were with the FileUpload component which is based on Apache Commons File Upload and the ImageCropper component which references Java’s imageio classes which are blacklisted.
Although Google states that the Apache Commons IO is compatible, one class, org.apache.commons.fileupload.disk.DiskFileItem references java.rmi.server.UID. All java.rmi classes are blacklisted in GAE. The UID was used to define a unique temporary file name and was referenced in a static variable. Since GAE doesn’t support server-side files, the reference was redundant. Breaking the link and rebuilding the libraries solved the problem. I also configured the Primefaces File Upload Filter to never create a a file by setting the thresholdSize parameter to an impossibly large value. I don’t use ImageCropper so that wasn’t a problem.
The JPA migration was more of a problem. Since the GAE data store is not relational and JPA is targeted at relational databases, a lot of the JPA functionality is not supported. I coded around the unsupported portions and tried to execute. I got a lot of exceptions. In tracking down the errors, I saw that there had been a lot of issues filed for JPA. I decided to look elsewhere. The JDO implementation seemed more stable, but JDO is also is targeted at relational systems. I took a quick look at the Google low level API and then I found Objectify (http://code.google.com/p/objectify-appengine).
Objectify runs as thin layer over the low-level API and provides a programmer-friendly interface to the GAE data store. My persistence logic consisted of entity classes generated from the database by Netbeans. I also had controller classes for each entity. This approach fit nicely with Objectify. I was fortunate that almost all my key fields were Long type which is the preferred type for Objectify. Objectify even implements auto key value generation on Long keys. I did an in-place conversion that consisted more of removing code than anything else. I converted my relationships by using the Objectify Key class. The Objectify Key class improves on the GAE data store Key class by introducing type sensitive key values.
Objectify does have one requirement that is different from JPA, that all entities must be registered. I wrote an auto-start servlet that accomplishes that. It runs every time the server is started. This is also a good place to put global data store initialization code. For instance, when running locally on Netbeans, GAE places all data store files under the build directory. But the build directory gets wiped when you do a clean and build in Netbeans. So I put a check in the servlet to see if the database had been deleted. If so, I re-initialize. I ended up with about one-third less persistence code and it is a lot cleaner and more intuitive. The idea of not having to do an object-relational mapping really appeals to me. No more crossing the object-relational divide.
I am currently at version 1.3.7 for GAE, 2.2M1 for Primefaces and 2.2.1 for Objectify and everything is going well.