Friday, June 12, 2009

Google App Engine for Java - 3 Tips for Getting Started

Google announced an early look at Google App Engine for Java on April 7th and I have been using it ever since. Google App Engine for Java is a web application hosting service provided by Google and designed for services that expect rapid growth and, thus, it is ideal for applications that aspire to need a scalable infrastructure.

In an attempt to be a recession proof Java programmer, I created a new niche microblogging service, http://m.TwoKnobbyTires.com, for outdoor enthusiasts, fans of pro sports, and fans of college sports. It runs on Google App Engine for Java and I hope that someday it will warrant the scalable infrastructure that App Engine provides ;). My microblogging service uses Google Accounts for authentication, App Engine's email service, and the default open source JDO implementation provided by DataNucleus. The following is a getting started guide for programmers considering Google App Engine for Java. For more details about Google App Engine, read Google App Engine For Java - A Microblogging Case Study.
  1. Start with a new application - App Engine for Java does not support the full Java specification nor all of the frameworks that run on the Java platform. For example, it supports JSTL (allegedly), Java Servlets, and JSPs but does not fully support Struts 2, JDBC, JSF, Hibernate, and EJB. Thus, it is best to start with a new application rather than attempt to port over an existing application that may have compatibility issues. My service runs using plain old Servlets and JSPs; plus Servlet Filters are employed for site wide tasks like pre-loading user data and closing database connections.
  2. Acclimate to Google's non-relational data store - Google's database is non-relational which was a challenge for me since I have only worked with relational databases (e.g., Oracle, MySQL) . Specifically, Google's database is an object datastore without a schema which means that join queries are not supported and the responsibility for data integrity lies within your code. Some of the data integrity responsibility can be managed by JDO or JPA in the form of one-to-one, one-to-many, and many-to-many relationships. However, I needed to manage some of my object relationships and queries outside of JDO because the JDO annotations plus Google datastore limit the number of relationships an object can have. My application is still experiencing random DatastoreTimeoutExceptions and I have not figured out whether my database is poorly designed or if Google's datastore has been experiencing hiccups in service.
  3. Automate tests - I used Fitnesse to automate HTML tests for web pages and XML tests for RSS feeds. Automated tests are a good idea regardless of your hosting service but in the case of Google App Engine for Java, there are two good reasons to automate tests:
    1. Auto generate the datastore index file - Your App Engine database on Google's servers requires a datastore index for every query your application needs to run. The easiest way to generate a datastore index file is to let the Eclipse plugin do it for you. Specifically, run every query in your development environment by using automated tests to trigger them and the Eclipse plugin will update the datastore index file after each query execution. Letting the Eclipse plugin generate the datastore index file is easier and less error prone than writing a datastore index file by hand.
    2. Quickly adapt to internal redesigns and platform changes - I redesigned the internals of my application several times during the process of adjusting to Google's non-relational datastore. In addition, the Google App Engine for Java platform and service are still under active development. Thus, it is important to create an automated testing suite that can provide rapid feedback on the health of your software so you can quickly and confidently adapt to both internal changes (i.e., your need to redesign to support new features) and external changes (i.e., Google's updating of the App Engine platform).
Retrospective

In the past, I compared Java vs. Ruby on Rails and my analysis ended in a tie. I believe that Google App Engine for Java tips the scales back in Java's favor because it solves Java's biggest long-term problem: a lack of affordable, scalable hosting for entrepreneurs. However, I am not convinced that Google App Engine for Java is enterprise ready because there are still too many unsupported Java APIs and frameworks.

11 comments:

  1. i come to this post from the appengine list, thanks for sharing!

    ReplyDelete
  2. Also have a look at http://marceloverdijk.blogspot.com/2009/06/google-app-engine-datastore-doubts.html

    ReplyDelete
  3. Check out Stax [www.stax.net]. It's a Java app engine built on top of Amazon's cloud that solves some of Google's problems. Like Google, Stax is still in beta and probably won't be free once it goes live, but for now provides for interesting comparison.

    ReplyDelete
  4. Stax looks interesting. For a year, I used Amazon EC2 and S3 to host Ruby on Rails applications but felt like I was spending too much time performing server administration tasks. Stax will be compelling if it simplifies hosting in a similar fashion to Google App Engine.

    ReplyDelete
  5. I think you should seriously try GWT. Works great with GAE/J and is really the easiest AJAX development solution I ever used by far...
    Also GAE/J supports JPA which has some advantages over JDO and is very similar to Hibernate.

    ReplyDelete
  6. "However, I am not convinced that Google App Engine for Java is enterprise ready because there are still too many unsupported Java APIs and frameworks."

    +1. I spent a lot of time playing around GAE 4 Java, and kept running into the fact that it does not support the full JRE. This is a huge limitation especially when you start working with 3rd party APIs which may or may not work in GAE 4 J. Google does a lot of nice work, but in IMHO it is breaking Java by not supporting the full JRE in many of its products (GWT, GAE, Android). So much for write once run everywhere.

    Also, I found the datastore performance to be slow and non-scalable.

    ReplyDelete
  7. Shai, I hope to try GWT soon but wanted to limit my learning curve and develop a service that would work from mobile devices. I have not looked into JPA for GAE, what are the advantages over JDO?

    Julien, I agree. I didn't know that Google was also limiting the JRE on Android :(. A big strength of Java is its open source software so it is unfortunate that Google does not support the full JRE.

    ReplyDelete
  8. Grails ( http://www.grails.org/ ) now runs on GAE ( http://www.springsource.org/node/1471 ), although not all the plugins are available. It uses JPA for persistence, instead of the standard Grails Hibernate mappings etc. But this gives you a quick route into Rails-style Java-compatible web-apps on GAE. Groovy/Grails is a great combination, and Groovy/Grails on a cloud platform like GAE may yet be a real killer app.

    ReplyDelete
  9. Chris, thanks for the comment. I watched the screencast. Grails on GAE sounds like a win-win situation for Java developers. Does grails auto generate the datastore index file? Does the data migration functionality work on GAE servers?

    ReplyDelete
  10. Would you mind sharing any experience that you gained getting around the GAE Datastore's lack of 'IN', 'LIKE' and 'OR' support?

    I'm looking at having to repeatedly retrieving around 20~25 items using a set of key values - a perfect fit for an 'IN' or 'OR' clause.

    Did you end up doing multiple separate fetches or did you find a work-around for this issue?

    TL

    ReplyDelete
  11. Thomas, if you do not have that many keys then you can create a key for every possible combination. For example, I used numeric values to represent different combinations (e.g., 1,2,3,4) or you can do "A", "B", and "AB". Another option is to see if you can come up with a way for your Java code to perform a post query filter on a CSV value or collection of strings; or use regular expressions on single text field.

    Do any of the aforementioned options solve your problem?

    ReplyDelete