Sunday, January 22, 2012

Database migrations with deployed JRuby WAR files

In my previous post Compiling Rails project for distribution in a WAR file with JRuby, I explained how to build a  WAR file from a Rails project to distribute on to systems that have a Java app server like Tomcat or Glassfish.  If you're running this in production, you're probably going to want to run database migrations after the WAR file is deployed.  Unfortunately this is not as straightforward as you might expect.  But it's not too difficult.  To run database migrations, you must first create a file in your project, config/warbler.rb with the following contents:

Then, add a file named script/db_migrate with the following contents:

Now, on the production system, after the WAR file has been deployed, from the root directory of your web app, run the command:

jruby -S ./script/db_migrate

If you're running in 1.9 mode, add --1.9 before the -S. This assumes that you have a jruby executable in your path somewhere on the server. There should be a way to run the JRuby that is bundled in the WAR file, but I have not spent enough time looking in to it to figure out how. Has anyone had success with this?

Tuesday, January 17, 2012

Compiling Rails project for distribution in a WAR file with JRuby

I recently started using JRuby for a Rails project and overall the experience has been excellent.  Using RVM, you can just switch to jruby to build a new project (rvm use jruby), and just about everything will work the same.  One of the big features of JRuby is that you can bundle your entire app, including JRuby itself, in to a WAR file that Java servers like Tomcat and Glassfish can serve up, so your app can be distributed on to servers that only have Java.

After you have JRuby installed, simply install the gem warbler.  You'll then get a command line tool, warble, to generate war files from your project.  Simply run warble from your project's directory, and a war file will be produced.  It's as easy as that!

Another great feature is that the Ruby code can be compiled down to Java class files, so your source code is not visible.  This is great for distributing on to a server where other companies will have access that you don't want seeing your source code.  However, this is not working for me.  Warbler should support this, just run "warble compiled war" from the command line in your projects directory instead of "warble".  This will produce a war file with both .rb and .class files.  The .rb files however are simply stubs that require the .class file, none of your code is in there.  But, for me, it's not generating .class files on all of my controllers.  I've entered an issue for this at

I will be making another post on how to do database migrations on the server you're deploying to.

Wednesday, January 4, 2012

Rails 3.1 "Could not find a JavaScript runtime" error

I just got my first Rails 3.1 on JRuby project created.  However I keep getting the error "Could not find a JavaScript runtime ..." when trying to do pretty much anything with it.  After digging in to this some, it turns out that with the addition of CoffeeScript in 3.1, Rails needs to run Javascript code natively.  A gem called execjs was added to Rails to allow this.  EXCEPT, execjs itself needs something else to actually evaluate the Javascript.    See for a list.  If you're running in Mac or Windows, you're good, there are system libraries to do it.  But if you're in Linux, unless you have node.js installed, it won't work.

Let me repeat that.  Rails 3.1 apps by default will NOT work in Linux, unless you have node.js installed.  This is absolutely ridiculous... guess what Rails team, a lot of people are developing in Linux and not Mac.  I understand how stuff not working in Windows is released, but Linux??

So to get things to work you'll need to add one of the gems listed on the execjs page.  If you're running the MRI Ruby, just add:

gem 'therubyracer'

to your Gemfile.  I've read a lot of complaints about therubyracer.  But it appears to be the most popular.  If you're running JRuby like me, add:

gem 'therubyrhino'

to your Gemfile.  I've verified that this works correctly.

FOLLOW UP 1/13/2012:
See my comments.  I have made a fix to Rails to put the appropriate gem in the Gemfile if you are in Linux, and issued pull requests to the Rails core to incorporate this code.  They have made some comments on it, hopefully it will be pulled in to Rails soon.