Hello, JRuby Rack and Glassfish
Thu Aug 14th 2008, 2:29pm
Rack "provides an minimal interface between webservers supporting Ruby and Ruby frameworks" and JRuby Rack is its logical extension to Java servlet containers. The latter states "JRuby-Rack supports Rails, Merb, as well as any Rack-compatible Ruby web framework." While Warbler makes deploying Rails apps to Glassfish and other Java servlet containers easier than ever, there are scant few (or at least, none I could find) examples of deploying any old Rack-based Ruby web application to Glassfish. So here's what I figured out.

Basically, create a war file with a web.xml, jruby-complete-1.1.3.jar, and jruby-rack-0.9.1.jar. Here's the directory structure I used to build the war:
$ find .
.
./WEB-INF
./WEB-INF/lib
./WEB-INF/lib/jruby-complete-1.1.3.jar
./WEB-INF/lib/jruby-rack-0.9.1.jar
./WEB-INF/web.xml
Grab a precompiled version of jruby-complete-1.1.3.jar or follow these instructions to build it from the source. Likewise, grab jruby-rack-0.9.1.jar. (I had local copies of both from using Warbler to build a war for one of my Rails apps, look around).

Here's the "tricky" part, the web.xml, with the interesting parts in red:

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

  <context-param>
    <param-name>public.root</param-name>
    <param-value>/</param-value>
  </context-param>

  <context-param>
    <param-name>rackup</param-name>
    <param-value>
       app = lambda { |env| [200, {}, 'Hello World!'] } 
       run app
    </param-value>
  </context-param>


  <filter>
    <filter-name>RackFilter</filter-name>
    <filter-class>org.jruby.rack.RackFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>RackFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>org.jruby.rack.RackServletContextListener</listener-class>
  </listener>

</web-app>


The rackup parameter is the key, it glues the servlet to your backend application (I see in the TODO is to allow this script to be defined in a file instead of in the web.xml). The value of the parameter is a simple Rack-compliant application, borrowed from this Rack presentation.

You can build a war from this:
$ jar cvf ../test.war
*added manifest
adding: WEB-INF/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/lib/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/lib/jruby-complete-1.1.3.jar(in = 7341701) (out= 6541093)(deflated 10%)
adding: WEB-INF/lib/jruby-rack-0.9.1.jar(in = 192848) (out= 53055)(deflated 72%)
adding: WEB-INF/web.xml(in = 794) (out= 351)(deflated 55%)
and deploy it to your favorite Java servlet container. Hit it with your browser and you should see "Hello World!" It's amazing, it just works.

Baby steps! Next to figure out is how to get a full Rack-compliant app, like something built using Ramaze, running in Glassfish.

Thanks go to this post, which was very helpful in figuring out what to do.



Visitor comments
On Tue Aug 26th 2008, 8:22am, Chris Schneider posted:
Thanks for the link to my blog (http://www.gittr.com). I haven't gotten around to writing a post about it, but Nick Sieger (the jruby-rack maintainer) added a patch that fixed the issue I was running into with Sinatra. $0 is now set to the .xml file, or something along those lines.