Rails on App Engine: A Cold Start

by Michael Sofaer

I’m at RailsConf ‘09 and I want to get a “Hello World” style Rails app running on Google App Engine, from a totally cold start, without any dependencies.  A lot of this is available in various places on the net, including Dan Kubb’s sample Datamapper Rails app, and Ola Bini’s Rails on GAE post.

But I didn’t find anything that would get you through the whole process on one page, so as I beat my head against this (with lots of help!), I will put it all together, here.  I got a lot of in-person help from @headius and @ridrdb, so lots and lots of thanks!

These steps are for Windows, but the basics are probably the same on any OS.  Let’s go!

Step 1:

Install the latest Java JDK on your machine.  You get no link from me here, I’m sure you can find it.

Step 2:

Download the JRuby complete package.  The one I got was http://dist.codehaus.org/jruby/1.3.0RC1/jruby-bin-1.3.0RC1.zip

Step 3:

Unpack the zip into a convenient directory.  I used C:/jruby, so you should, too.

Step 4:

I removed all my MRI (That means Matz’s version of the Ruby interpreter) directories from my path.  I didn’t want to hit any Ruby stuff that wasn’t JRuby by accident.   You can also prefix everything with jruby -S instead of doing this.

Step 5:

Put your jruby bin folder in your path (C:/jruby/bin)

Step 6:

Make sure JRuby works:  Open a new console and type jirb.

>> 2+2
=> 4
>> exit

Step 7:

Install the gems you need:

gem install jruby-openssl rails warbler appengine-apis

Ola calls for gem install warble, which doesn’t work.  Warbler includes jruby-rack, so you don’t need to download that separately.

Step 8:

We need the Google App Engine SDK.  Get the one for Java:

http://code.google.com/appengine/downloads.html

And put it in your path somewhere

(I put it in c:/jruby)

Step 9:

Get Dan Kubb’s Rails App with datamapper

git clone git://github.com/dkubb/datamapper-on-rails.git

If you don’t have git you, can get the zip file:  http://github.com/dkubb/datamapper-on-rails/commits/master and click download

Step 10:

Remove the DB gems from config/environment.rb

(sqlite3 and datamapper)

Add the gems you need:


config.gem 'rails'
config.gem 'appengine-apis'

Require the GAE apis gem’s logging
require 'appengine-apis/logger'

Set up GAE logging
config.logger = AppEngine::Logger.new

Once Datamapper 10 is out, @ridrdb’s datamapper interface for Google Datastore will work.  Until then you can access Datastore directly from the Ruby API, but for the sake of this post, we’ll just punt on data storage at all, and use totally vacuous controllers.

Step 11:

Pluginize warble in your app

jruby -S warble pluginize

This didn’t work for me due to some Windows nastiness, so you can do this:


cd vendor/plugins
gem unpack warbler

Step 12:

jruby -S warble config

Step 13:

Edit your warble file similarly to the way Ola says to.

You need to set the parameters for how many runtimes will be started:

config.webxml.jruby.min.runtimes = 1
config.webxml.jruby.max.runtimes = 1
config.webxml.jruby.init.serial = true

The last option is available in trunk version of JRuby-rack. If you don’t have min=1 and max=1 then you need this option set, because otherwise JRuby-rack will actually start several threads to initialize the runtimes.

Set your environment to development mode:
config.webxml.rails.env="development"

If you use copy paste here, make sure your quote characters aren’t insane

Finally, to be able to use newer versions of the libraries, you need to set what Java libraries are used to the empty array:
config.java_libs = []
Step 14:

Use warbler to refactor your application setup

warble

This will break, but it gets far enough.  It should create a tmp/war directory, which is your new application home

Step 15:

Move to your new home!

mv tmp/war ../warbled_dm_rails_gae

cd ../warbled_dm_rails_gae

Step 16:

Create a file called appengine-web.xml in your WEB-INF directory, with this in it:

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>msofaer-gae-test</application>
<version>1</version>
<static-files/>
<resource-files/>
<system-properties>
<property name="jruby.management.enabled" value="false" />
<property name="os.arch" value="" />
</system-properties>
</appengine-web-app>

Step 17:

Create your WEB-INF/lib directory

You need four jar files in it.  Eventually warbler will handle creating them, but for now you can get the lib directory here:

http://github.com/MikeSofaer/rails_gae_lib/tree/master

Step 18:

Delete your vendor directory

Delete ActiveRecord from WEB-INF/gems/gems

Step 19:

Start the server

dev_appserver .

(If you’re not on Windows, dev_appserver.sh .)

Step 20:

Test the server

http://localhost:8080/rails/info/properties

You should get your env properties

Ruby version 1.8.6 (java)
RubyGems version 1.3.2
Rack version 1.0 bundled
Rails version 2.3.2
Action Pack version 2.3.2
Active Resource version 2.3.2
Action Mailer version 2.3.2
Active Support version 2.3.2
Application root C:/Users/mike/git/warbled/WEB-INF
Environment development

Now your application is running in dev mode!  Add a route and a controller that does something, restart, and check it out.  From here you can develop your app in a local environment just like GAE, until you deploy it.

Step 21:

Sign up for the Java GAE access:

http://appengine.google.com/promo/java_runtime

Eventually you will get an email, (keep developing on your local machine)

Step 22:

Jar up your application.  Go to your gems directory (the first one)

jar cf ../lib/gems.jar gems specifications

Then delete your gems directory.

Step 23:

Create your application on the GAE panel:

http://appengine.google.com/start

Step 24:

Put your app ID into your app’s appengine-web.xml:

<application>rails-gae-test</application>

Step 25: Upload your app

appcfg update .

Step 26:

Go see your Rails app on app engine!

Here’s the tiny little controller response I built for testing:

http://rails-gae-test.appspot.com/responses

=> Hello, I hear you

So it’s been a long trip, and it’s not exactly pretty, but there it is.  Victory!


Tagged In: , ,

8 Comments

Dan Kubb
May 8, 2009

Wow, that’s quite alot of steps :)

In talking with the guys at Google, I think it’s safe to say they are really committed to making the process as simple as possible.

For my part I’m going to make it so DataMapper can be used with Rails with a drop-in plugin. It shouldn’t be too hard.. I think within the next week or so I should have something working well.

Pankaj
Jun 3, 2009

msofaer, very well described!

I got the error following error,
javax.servlet.ServletContext log: unable to create shared application instance
org.jruby.rack.RackInitializationException: no such file to load — appengine-ap
is/logger

Michael Sofaer
Jun 3, 2009

Thanks, Pankaj!

It looks like maybe I left off a step! I thought the logger API was included in the AppEngine API things you got from Google, but if it’s causing you a problem you can take out the lines that require it from config/environment.rb.

Let me know if that works!

Pankaj
Jun 4, 2009

Thanks msofaer!

I ran the app by commented the appengine-apis/logger.But getting following exception.I have installed the appengine-apis gem.What I am doing wrong?



Missing these required gems:
appengine-apis

You’re running:
ruby 1.8.6.287 at file:/D:/Rails2/JRuby/GAE/new/gae/war/WEB-INF/lib/jruby-stdl
ib.jar!/META-INF/jruby.home/bin/jruby.bat
rubygems 1.3.2 at D:/Rails2/JRuby/GAE/new/gae/war/WEB-INF/gems, file:/D:/Rails
2/JRuby/GAE/new/gae/war/WEB-INF/lib/jruby-stdlib.jar!/META-INF/jruby.home/lib/ru
by/gems/1.8

Run `rake gems:install` to install the missing gems.
Jun 4, 2009 1:31:07 PM com.google.appengine.tools.development.ApiProxyLocalImpl
log
SEVERE: [1244102467532000] javax.servlet.ServletContext log: unable to create sh
ared application instance
org.jruby.exceptions.MainExitException: aborted


Caused by: org.jruby.exceptions.MainExitException: aborted

The server is running at http://localhost:8080/
Jun 4, 2009 1:31:16 PM com.google.appengine.tools.development.LocalResourceFileS
ervlet doGet
WARNING: No file found for: /rails/info/properties.html

msofaer
Jun 4, 2009

Pankaj

Try “gem install appengine-apis”

Pankaj
Jun 4, 2009

Hi msofaer,

It’s working now.I have generated the jar file of appengine-apis and included it under lib folder.

Can you provide some light on usage of datamapper?

Thanks

msofaer
Jun 4, 2009

I’m glad it’s working!

I didn’t actually use Datamapper, since 0.10 wasn’t out yet (it is now) and is needed for the datastore adapter, so I can’t give you much guidance on using it for Google Datastore, other than to tell you it’s supposed to be supported. Once you get it working, you could make a blog post!

Pankaj
Jun 5, 2009

Thanks msofaer!

Leave a Reply

Comment