I’ve been working on a little piece of Ruby-and-Rack-based Web integration goo, and it’s done enough that we have to figure out deployment. One reason I picked Rack is that it’s advertised as deploying on anything. The environment where this will live has some of this and some of that, and we’re using GlassFish to tie it all together, which seems like an appropriate choice. So, the problem is: How to plug a simple Rack application into GlassFish?

[Update: It’s been suggested by several that all I need is the GlassFish Gem; see also Vivek Pandey’s Plug-in any Ruby/Rack based framework to GlassFish. Perhaps that would have been a better approach. My concerns were first, my impression (perhaps wrong?) that the gem brings along a large amount of Rails stuff and so on, probably not appropriate in an Internet-facing server when you’re not using that stuff. Second, that my code is heading for a large hosting environment, run by its own group, where lots of code aside from mine is being run by an army of GlassFishes; they want a .war that they can manage according to their policies. In any case, the gem might work for you.]

GlassFish is Java-land so we want JRuby. Fortunately, our own Nick Sieger has done a bunch of work on this problem, most of it encapsulated in JRuby-Rack (also see here) and Warbler (see also here and here and here).

Pretty quickly, you discover that for real Rack pipe-fitting you’re going to need Rackup. You’ll notice that name has no link; might a reader suggest one? Rackup is, um, lightly documented. I found (Tutorial) Rackup HowTo and A Passenger Rackup File for Sinatra. Rackup is based on the Rack::Builder DSL, whose documentation is thin even by Ruby’s forgiving standards.

OK, I’ve moaned enough. Here’s how to hook up a minimal Rack application for GlassFish. Let’s assume you have a class Whatever whose call method you’ll be asking Rack to invoke for each incoming request. You’ll need to make an instance of Whatever, probably initializing it with all sorts of configuration info specific to your app. Here we go:

  1. Make sure your app runs under JRuby. It’s a pretty easy install, and if you’re like most people, you’ll discover instantly that you’re relying on a whole bunch of gems. No problem, JRuby has its own gem command, so go get ’em. For JSON you’ll want json_pure and if you’re doing any secure Net stuff jruby-openssl.

    My app was fairly lightweight, only a couple thousand lines, and once I got the gems, all the unit tests ran and then it worked first time.

    To make sure things were working, I ran it under Mongrel just like I had been with native Ruby (Mongrel comes in a J-flavor too).

  2. Install GlassFish. The download I got was a .sh file, and the installer was an ugly Swing app, but it did what I wanted and got out of the way. There are lots of docs online about how to start and stop and manage GlassFish.

  3. Now you’ll need a Rackup config file, which by convention is called config.ru. It took me a while to figure out that it’s actually read by the Ruby interpreter, so you can do your object initialization here using as much Ruby as you need. As for the parameters to initialize your Whatever object, there are lots of ways to get them in: YAML, web.xml context attributes, JNDI, whatever.

    At the top of config.ru, you might want to to have a
    $LOAD_PATH.unshift ... to make your app files loadable.

    Thus, the second last line of config.ru probably looks like
    w = Whatever.new(....)
    and for your last line, use
    run w

  4. Now set up Warbler, which is just another gem. Warbler will take your Ruby project, read config.ru, and pack it all into a .war file that you can drop into GlassFish; it contains everything you need, starting with JRuby itself

    By default, Warbler assumes you’re running Rails and sets up all sorts of stuff for that. The first time you run warble, it makes a file called config/warble.rb, which is really a nice piece of work; it shows you all the options you can set, with the default values, and provides commentary and example code for how you might go about changing them. You are almost certainly going to want to change a few things. I told it to include the gems my code needed, not to include Rails, and give my .war a nice friendly name.

    Once you’re ready to go, just type warble and you’ll get your .war file. It’ll be big, because it contains more or less all of Ruby and the gems you need; mine was over 10M in size.

I think that’s about it; you’re ready to go with any old Java app server now. There is all sorts of app-server-fu about how and where you deploy things; I’m no expert and you probably have Operations types who live and breathe this stuff anyhow, and will tell you how things have to be.

As of now, nobody can tell from the outside that my code is now running on GlassFish instead of Mongrel, except for the first couple of requests are slower, and all the rest are faster.

(Thanks to Nick Sieger for advice.)



Contributions

Comment feed for ongoing:Comments feed

From: Vivek Pandey (Apr 18 2009, at 01:13)

You can cut down lost of steps. With glassfish v3 all you need is this: http://is.gd/t6AB, a Ruby friendly way, no need to WAR. This is a minimal Rack+Ruby for GlassFish combination as you would do with Mongrel. It would work with both GlassFish v3 (trunk builds) as wel as GlassFish gem.

[link]

From: Rob Britton (Apr 18 2009, at 08:12)

Don't forget to include all your gems in config/warble.rb or they will not get packaged into the .war (at least mine don't).

[link]

author · Dad · software · colophon · rights
picture of the day
April 17, 2009
· Technology (81 fragments)
· · Java (123 more)
· · Ruby (93 more)
· · Web (388 more)

By .

I am an employee
of Amazon.com, but
the opinions expressed here
are my own, and no other party
necessarily agrees with them.

A full disclosure of my
professional interests is
on the author page.