Some time back (around the 2nd week of May '09) I deployed my Jirb Online web application on Google App Engine for Java (GAE/J): http://jirbonline.appspot.com
It was not as straightforward as I'd hoped but was an interesting experience that gave me some insights into dealing with GAE/J and JRuby. This is how I went about it:
I registered for the GAE account and got an invite for trying out GAE/J. I registered using the mobile phone option: you get a code via sms that you need to complete the process. The Vodafone network in India failed to deliver Google's sms to me but IDEA worked. I got myself: http://jirbonline.appspot.com
After reading up some documentation, I installed the Eclipse GAE/J plugins. However, I did not intend to use Eclipse for my development (as I already had an existing app); I did use the SDK that got installed as part of the plugin.
I created an appengine-web.xml for my app and added the necessary jars. I also created an ant build file to manage my project. This is most convenient, I feel, especially if you like doing things from the command line.
Once ready with the local setup, I tried running my application on the GAE SDK's dev server. This is where I realized that JRuby 1.1.x (that's what I was using) will not run on GAE/J due to threading restrictions. I'd end up with a SecurityException. Thankfully, the JRuby team was on its toes and just a few days back had released JRuby 1.3.0RC1 which does run on GAE/J.
I quickly replaced the existing JRuby jar with the one for JRuby 1.3.0RC1. I could now deploy on dev server but it was not of great use because my JUnit tests were failing. Apparently, the behavior of the evalScriptlet() method of the org.jruby.Ruby class has changed since JRuby 1.1.x to JRuby 1.3.x to not retain context over multiple invocations. Hence, evaluating i = 'str' and subsequently, puts i would lead to a NameError as i would be unrecognized.
I went through the JRuby wiki but couldn't find hints about the change. The recommended way to evaluate scripts is to use Java Scripting Engine or BSF. So I got hold of the Java Scripting Engine for JRuby in the form of jruby-engine.jar.
But this did not help pass my tests as till the date of this writing, the scripting engine supports JRuby only till version 1.1.6. The JRuby APIs that the engine uses have over time changed in signature. I've confirmed with Ola Bini that so far an updated JRuby scripting engine isn't available (the JRuby team is not the one behind the engine).
So, ultimately, I had to fall back upon the JRuby APIs for my implementation. I did get hints from the code of the JRuby Scripting Engine.
I now had my tests passing and could also successfully deploy the app on the dev server. However, as soon as I made the first request to the app to evaluate a script, the app would bomb. This was because I'd configured DWR to create and keep the RubyInterpreter object in session scope. However, in GAE/J, sessions are by default turned off, and have to be explicitly turned on in appengine-web.xml.
After turning on sessions, everything seemed to work perfectly on the dev server, and I finally uploaded my app to GAE/J. But there was yet another hurdle: the session approach did not work on the real server as I got a NotSerializableException for my RubyInterpreter class.
On second thought it does seem to be an obvious error but I guess I never noticed that my class was not serializable because it did not matter when I'd deployed my application on Tomcat or even on GAE/J's local dev server. Neither of these ever tried to serialize my objects onto a file system or something.
I now had to think about how to serialize the context of my interpreter because otherwise, I'd end up with the situation I described sometime back (variables not being accessible across invocations). The JRuby runtime is not serializable. My best attempt could be to try and individually serialize/deserialize all the objects created in the runtime. That could take a while to test and implement, so I went for the quickest approach: serialize all the inputs received so far, and deserialize and re-execute them each time. This would work for the general case but not for variables that are dependent on time or the system (eg: variables initialized to current time, or via the random method, and so on). I had to implement the readObject(ObjectInputStream in) method to have this custom deserialization step.
This is where my application currently stands with respect to GAE/J. I hope to tinker around more to see the possibilities of what I can transform my app into.