Friday, December 25, 2009

Google Data API, Google App Engine and Scala/Lift

Recently I decided to bite off this chunk of coding. What followed really emphasized and reinforced the title of this blog. It was quite frustrating at times, frequently interesting and in the end, rewarding. I did finally get most everything to work, so here are my notes...

The objective of the particular web site I did was to have the user enter a handful of values via the web page, run a model calculation based on those values and display the results. Prior to my involvement, my colleague had done all the modeling in Excel and VB. His next step was to export the data to XML files and re-code the calculations in Java.

My first step was to make the site run with Scala and Lift and let the Java code read the XML files. No problem.

Step 2: host the app somewhere. I had read a lot about Google App Engine (GAE) and knew people who had good luck with it. Great idea.

First roadblock: I had read GAE doesn't support static data files, but that's no problem there's the GData API, and all these XML files came from spreadsheets anyway, so how hard could it be?

First sidetrack: instead of reading static files and short of migrating to the GData API, it seemed I should be able to read XML files from the Jar files: ClassLoader.getResource("xmlfile_name"). I spent many hours and never did get this to work!

At this point it became clear - the GAE support for Java seems to be WAY behind the Python support/documentation/functionality/etc.

GoogleData API
It seems there are several variations on this, but the REST API model seems to be quite adequate. There are however a handful of glitchs/gotchas it seems.

1) I created a user which had only view authority on a spreadsheet. Unfortunately, it could *not* read that spreadsheet with the REST api.
2) Everything comes back as a string. This is not too bad, but it seems a more "robust" API would provide a bit more flexibility.
3) The column headings are used as the key to a map of the values in each row. This is a decent strategy, however I would like access to the actual value in the header, not the munged value used in the key. Again, not a complete deal-killer.

Google App Engine
I did get everything running just fine with the Gdata api within those constraints. Now it was time to deploy. I had read several people deployed with no problem and sure enough, there are a handful of apps running with Scala/Lift.

Would mine deploy? Of course not. It generated a couple stack traces indicating problems in the LiftFilter, but seemingly in the configuration of the logging. Might that be just a 'warning'? You would think so, but NO. What the heck? Well, 5 combo boxes aren't that big a deal, so I rewrote them in JSPs and it deployed just fine. As always, appetite grows while dining and the client wanted the drop downs to repopulate based on certain selections. No problem - but wait! That was why I wanted to use Lift in the first place! Ack. The long and the short of it was all I had to do was get a more recent version of Lift (specifically 1.1-SNAPSHOT), and it deployed just fine!

Miscellaneous Glitches
Because it is a proprietary application, I set the security of the main site to be limited to the registered users of a domain I had authorized in Google Apps. This works quite well - the user is redirected to a login page, then to the web site. Cool. Now I added a page to allow an admin user to reload the app. The documentation describes a really easy way to do that. The fine print I didn't digest the first time around is that the members in the admin role are those users defined as admins of the application. Oops. I'm the admin of the application and I created it from my main Google account which is NOT in the aforementioned domain. Oh, I can add admins, so email has been sent inviting another user I created in that domain. Now, where did that email go?

Pleasant Surprise
All the while I was developing the app, I was wondering about releasing new versions after it was in production. I only uploaded code a couple times before I encountered the concept that GAE has the idea of versions of your application. Several versions can be stored on the server and run independently and simultaneously! Well done, GOOG.

Bottom line: Google App Engine and GData API are a good way to go. Better if you're using Python, which is not a bad choice. I just have a lot of legacy Java code, so I'm really liking Scala and Lift. Now I know, those are GAE-compatible also, so life is good.