Amidst the wretched events that happened at work recently, I forgot about an interesting development in running apps on a cloud. Google AppEngine finally released Java support on the AppEngine platform. For those uninitiated, AppEngine is Google’s cloud computing platform that allows developers to serve up applications on Google’s infrastructure. When it was first released in April 2008, the only language supported was Python. Python is a great language but doesn’t appeal to my inner Rubyist so it didn’t catch my attention. Until now that is.

The first thing you need to do is to create an application on the GAE/J. Start by going to this URL – http://appengine.google.com/start and log in using a Google account. After logging in, create a new application following the instructions given on the screen. When you’re done you should have an application id. In this case, it is ‘saush-snip’. We will be needing this application id in our configuration later. You will also need to enable Java for your GAE/J. At this point in time, GAE/J is still in beta and Google is only limiting the first 10,000 developers from enabling Java for GAE/J. Unfortunately if you don’t get Java enabled for your account, you won’t be able to try this out until it is fully released and available to all.

Once you have signed up and gotten an email approval for your GAE/J account, the first thing to do is to install JRuby, if you haven’t done so yet. Even if you have installed it previously you might want to install at least 1.3.0RC1 since some fixes were added into this release to make it run better under GAE/J. Run this:

$ git clone git://github.com/jruby/jruby.git

This will clone a copy of JRuby into your computer. Then go into the jruby folder that was just created and run this:

$ sudo ant && sudo ant jar-complete

This will install JRuby and create the jruby-complete.jar library that you will need in a while. Take note of this path to JRuby, you’ll need it in the subsequent commands. Assume that you just installed JRuby in ~/jruby, do a quick check to see if the install is ok:

After installing JRuby, you’ll need to install all gems needed for this application. Remember that even if you have installed gems for your normal Ruby installation you’ll need to install it all over again for JRuby. For Snip, you need Sinatra and HAML, but you’ll also need Rake and Warbler, the JRuby war file packager.

$ ~/jruby/bin/jruby -S gem install rake sinatra haml warbler

Now that the basic JRuby and related gems are done, let’s look at the Snip code itself. One thing that is pretty obvious upfront when dealing with AppEngine is that it doesn’t have a relational database for persistence. Instead of a familiar RDBMS, we get a JDO interface or a DataStore API. How do we use it? As it turns out, we don’t need to do anything major. Ola Bini wrote a small wrapper around DataStore, called Bumble, to allow us to write data models just like we did with DataMapper. Well, almost.

Using Bumble is very much similar to DataMapper and ActiveRecord, so I didn’t have to change my code much. This is the DataMapper version of the Url model:

I didn’t add in the time stamp for the Bumble version because I don’t really use it but as you can see there are quite a bit of similarities. I didn’t need to put in my own running serial id because it’s managed by the AppEngine. Also, instead of using the object id, I used the object’s key, which again is managed by the AppEngine. A key is a unique identifier of an entity across all apps belonging to the user. The key is created automatically by Bumble through the low-level DataStore Java APIs. Besides this, using the Url class is slightly different also. Instead of

@url = Url.first(: original => uri.to_s)

We use:

@url = Url.find(: original => uri.to_s)

Finally because we don’t use the id anymore and use the key instead, we don’t need to do the base 36 conversion so we let the AppEngine handle everything. Instead of:

get '/:snipped' do redirect Url[params[:snipped].to_i(36)].original end

The code is ready but here comes the packaging. GAE/J is a Java servlet environment, which means our app needs to be packaged into a war (Java Web ARchive). Fortunately instead of building up the war by hand we can use Warbler, the JRuby war packager. Before running Warbler, we need to have a couple of things. Firstly we need to build the warble configuration file:

$ mkdir config
$ ~/jruby/bin/jruby -S warble config

We create a directory called config and get Warbler to copy a default configuration file to it. Replace the contents with this minimal setup. If you want to explore more, read warble.rb itself.

Note that we don’t really need the public and view directories in Snip because everything is in a single file. The 2 other configuration files we will need are appengine-web.xml and config.ru. We also need to include the snip.rb and bumble.rb into the war file for deployment. To get bumble.rb, go to Ola Bini’s Bumble GitHub repository and get the file that is in the sub-folder (not the main one). The last line tells us not to include the jruby-complete.jar library in the lib folder when we run Warbler. I’ll explain this in a minute. Also note the war file is the application id of the application we created in the GAE admin console earlier on (saush-snip).

Next, create a lib folder. Go to the GAE/J download site and download the GAE/J Java library. It should be called something like appengine-api-1.0-sdk-1.2.0.jar. Copy that into the lib folder you’ve just created. We will also need the Java libraries in the lib folder. Normally for a JRuby deployment, Warbler will package it in, but Google has a 1,000 file limit which Ola Bini kindly pointed out. He also provided a script to split the JRuby library into 2 files. You can find the script here and when you run it, it should split jruby-complete.jar into 2 files named jruby-core-1.3.0RC1.jar and jruby-stdlib-1.3.0RC1.jar. You will also need JRuby-Rack but it’s included in Warbler and as you will see later, Warbler will copy it into the war when you run it. JRuby-Rack is an adapter for the Java servlet environment that allows Sinatra (or any Rack-based application) to run.

The next piece is appengine-web.xml. I used Ola Bini’s version as the base:

The list row in the property line sets logging to STDOUT, which is very useful for debugging. If you don’t set this, you might not be able to see any console output. Again, we need to set the application id that we got earlier on (saush-snip).

You will also get a saush-snip.war file and a bunch of files under the tmp folder, which is really just the war file exploded. We won’t need the war file (saush-snip.war) itself for deployment, only the tmp directory. Before doing the deployment, we need to make a minor adjustment to the tmp/war/WEB-INF/gems/gems/sinatra-0.9.1.1/lib/sinatra.rb file. Somehow the line ‘use_in_file_templates!’ gives an error when deploying to the GAE/J so comment it out.

That’s it! We are ready for the deployment. To deploy run this command:

A few thoughts on comparing Heroku and GAE/J since I’ve deployed on both of them now. Heroku is definitely the easier platform to deploy, with a just few simple steps compared to the hoops I had to jump for GAE/J. Heroku also has the arguably more familiar persistence mechanism as it uses the familiar RDBMS (postgresql) compared to Google’s DataStore implementation, which today only has Ola Bini’s Bumble implementation compared to the established ActiveRecord, DataMpper and Sequel ORMs. In addition, Google’s implementation has many limitations, some harder to understand than others, which forces applications to suit this platform rather than having the platform really service the application.

On the other hand, Google’s set of tools in its console is really impressive, with graphs of usage, data and log viewers. Google AppEngine also has memcached, url fetcher, integration with Google accounts, sending out mails and hosts of other helper services. Also, Google’s brand name does add some weight when you throw in more mission critical projects though Heroku, backed by Amazon’s EC2 services is no push-over. As for costs, until large deployments emerge it is hard to say which is the better deal, also it really depends highly on usage patterns.

So are they evenly balanced out? Not for me at least. For now I would still favor Heroku over GAE/J because Heroku is more friendly to Ruby developers. But who knows? It’s exciting times for Rubyists.

I tried JRuby for the first time in small project listed in my previous blog entry. While I wouldn’t say it’s love at first sight (or first use), it intrigued me sufficiently to try out other usages of JRuby.

What is JRuby? If you just think it this way — the Ruby that you and I know and love is a C implementation of the Ruby programming language — then JRuby is quite easy to understand. JRuby is the Java implementation of the Ruby programming language.

What the major difference and advantage in JRuby is that you’ll be able to define and interact with Java classes in Ruby directly. And that’s it. It’s not really different from Ruby, except that some built-in classes are not supported. And if you look at it from another angle, it’s not really that different between doing it this way (using JRuby) and using WIN32API or WIN32OLE, except of course you’ll need to know all the Java nuances and quirks.

Enter JRuby on Rails. Why JRuby on Rails? I think anyone who has done Java and Rails would be able to answer this one. It’s simply the vast ocean of Java libraries available, both good and bad, that gives JRuby on Rails the appeal for me. No doubt, the ‘enterprise’ factor of Java EE (i.e. running on a Java EE app server like Glassfish or the likes) is pretty appealing to those who care but I would say it’s not really worth it (at least at this point in time).

Let me run through quickly how you can deploy a JRuby on Rails application on Apache Tomcat 6. Why Tomcat? While there are a growing number of Java EE application servers out there, Tomcat is probably the one that most Java EE programmers cut their teeth and is most familiar with.

1. You’ll need to install JRuby. Installation is quite easy, just download the latest package from http://dist.codehaus.org/jruby/ and then unzip it into any directory.
2. Now set the environment variable JRUBY_HOME to point to this directory and set your path to point to JRUBY_HOME/bin. If you’re doing this all the time you should set this permanently.
3. Now quickly test your JRuby installation by typing ‘jirb’ on your console and then the following:

8. Check the rake tasks available now, you should have a couple of new rake tasks that starts with war:

$ rake –tasks
...
rake tmp:war:clear # Clears all files used in the creation of a war
rake war:shared:create # Create a war for use on a Java server where JRuby is available
rake war:standalone:create # Create a self-contained Java war
rake war:standalone:run # Run the webapp in Jetty

The tasks are pretty self explanatory.

9. There are a couple of things you need to change in the Rails configuration itself to enable Rails to run properly under a Java EE application server so you need to go into the config directory now.
10. Open up environment.rb and add these couple of lines in :

Remember to change both the development and production. You can point them to the same database, but right now, the Rails-Integration will redirect to the production database once you archive your application into a WAR. In this example, I’m using MySQL but you can use any JDBC URL to connect to any JDBC enabled database.

12. If you’re doing a new application, and you want to generate some code, remember to use JRuby and not the normal Ruby interpreter. For example, to create a scaffold for User (assuming you have done all the necessary table creation in your database of choice)

$ jruby script/generate scaffold User

If you can’t generate, go back and check out steps 9 – 11. Also to note is that you’re running Java as well, so check your classpath if you are missing the JDBC drivers for your database.

13. For instant gratification, run WEBrick on JRuby:

$ jruby script/server

And try it out quickly to ensure it works.

14. Onwards to make it work for a Java EE application server! First, you’ll need to add in any libraries you need into the Rails-Integration configuration, so that it’ll include that library when it builds the WAR file. Go to <your Rails application>/vendor/plugins/goldspike/lib/war_config.rb and add in your libraries. For example, to use MySQL, you’ll need to put in the MySQL drivers like this:

add_library(maven_library ('mysql', 'mysql-connector-java', '5.0.4'))

Browse around the code until you find a place to put this line.

15. We’re almost there. Run the rake task in your Rails application folder to create the WAR file:

$ JRUBY_HOME/bin/jruby JRUBY_HOME/bin/rake war:standalone:create

This will create the WAR file by archiving your code and any libraries needed to run JRuby. The first time you run it might take a while and you’ll need to be connected to the Internet in order for Maven to bring in the Java libraries from its public repository but subsequently it’ll be much faster. A problem I faced earlier on is that while getting some libraries, the connection will expire and creation is aborted. I had to run it a few times before it completes properly.

16. You’re done! You now have a WAR file that wil run on Tomcat 6 or Glassfishv2 (I tried both). Just deploy them normally as you would any web application.