Monday 30 April 2007

Packaging a Simple JRuby App Plus Gems

I've pretty much finished my first real ruby application. It's dead simple but does make use of two gems - Hpricot and simple-rss. Now, as I've blogged before the plan is to make this deployable as simply as possible to any system with a JVM available.

The big question I still had was how to package it? I was aware there had been some ruby magic going on while I wrote it what with the gems and everything but I did know that if I got a hold of the complete JRuby distribution available as a single jar file (the eponymous jruby-complete.jar which turned out to be a little hard to track down) I would be able to then just poke things into life with a simple "java" command:
java-jar jruby-complete-0.9.9.jar main.rb
I tried this and it worked perfectly. Until we hit one or my 'require' calls to the gems I'd used. How to get round that? I had a look around as usual. Ruby being ruby, the vast majority of information is on blogs, newsgroups and wikis. Unfortunately for me the JRuby wiki was down and all the blog entries were talking about far more complicated stuff to do with Rails. I was on my own...

So I had a look at the gems which I had installed. It's simple to find them (once you know where to look) just go to your ruby installation's home directory (CRuby or JRuby it's all the same) and then ".\lib\ruby\gems\1.8\gems". There you can see a list of all the gems your installation of ruby knows about:

You can see they are just directories. I had a look inside the aptly named "simple-rss" to see if what it contained made sense:


Seems simple enough. I read the README but it didn't tell me what I needed to know but the lib directory looked promising:


Only a single .rb file, excellent. I coped this to my project's lib directory (where all my .rb files live and ran the "java" command again. I was making progress, now the 'require' complaint was related to Hpricot.

Hpricot is a little more complicated. The standard version uses some components written in C. If you choose to download it manually from _why's subversion repo this is the one you will get.

NOTE: You can get most ruby libraries directly in this way without having to use ruby gems. Ruby Forge allows you to download them manually and if you open the archives you will find they have the same structure as when you use "gem -install" to get them.

Luckily, there is also a jruby version of hpricot for jrubyists which you can get via "gem -install". I looked in my jruby gems directory again and found the Hpricot gem:

A little more complicated this time but now I knew where I was going -./lib:

More than a single file this time but still pretty simple. I made an assumption that I could just do as I had before and just copy the complete contents of this folder across to my app. I did, ran the "java" command again and it worked. "Gordon's Alive!"

Loose Ends...
1. There are a few loose ends to tie up. I mentioned that the default Hpricot uses some C elements. These can be seen if you download the library manually and look in the ./lib directory. There, instead of "hpricot_scan.jar" you'll see "hpricot_scan.so". Not good for java...

2. It seems to me that if the jruby guys can package all the jruby bits and pieces inside a single jar, I could use the same method to package my bits and pieces with theirs and make my app a single jar file too. I'll blog about it when I figure out how to do this. In the meantime, I'm happy with a directory containing my ruby files, some html, the jruby jar and some shell scripts to keep me away from the command line.

No comments: