Introducing JRuby-Rack

Posted by Nick Sieger Thu, 08 May 2008 17:31:00 GMT

Continuing in the spirit of Conference-Driven Development, I’m happy to announce the first public release of JRuby-Rack! You can use it to run Rails, Merb, or any Rack-compatible application inside a Java application server.

Also released today is Warbler 0.9.9, which has been updated to bundle JRuby-Rack.

In addition to providing as seamless a connection as possible between the servlet environment and Rack, JRuby-Rack (along with Warbler) is also bridging the gap between Ruby and Java web development. Some of the things it does are:

  • Makes the Java servlet context and servlet request available to Ruby through special variables in the Rack environment
  • Servlet request attributes from Java are passed through and available in the Rack environment. Request attributes can override Rack variables such as PATH_INFO, QUERY_STRING etc.
  • Configures Rails deployment options such as page caching directories and session handling automatically and optimally for the servlet environment.

I’ve also included the beginnings of some extensions that should help integrate Rails with existing Java web frameworks, servlets, JSPs, and other code. For example, you can invoke a Rails request from within a JSP with a tag:

<jruby-rack:rails path="/projects/activity" params="layout=none"/>

You can set servlet and session attributes and forward to other servlets and JSPs from your Rails controllers:

class DemoController < ApplicationController
  def index
    servlet_request["hello"] = "world!"
    session["rails"] = "Visible to java!"
    forward_to "/attributes.jsp"
  end
end

and read them from within the servlet or JSP:

<dl>
  <dt><tt>servlet_request["hello"] | request.getAttribute("hello")</tt></dt>
  <dd><%= request.getAttribute("hello") %></dd>
  <dt><tt>session["rails"] | session.getAttribute("rails")</tt></dt>
  <dd><%= session.getAttribute("rails") %></dd>
</dl>

This is just the beginning of this kind of integration, and I’m interested where people take it. I think this provides a nifty way to start integrating Rails bits into existing applications or reuse existing Java web application code.

I’ve tagged the release with an 0.9 version number. I believe the bits are ready for serious use, but could use some help pounding out a few more bugs before calling it 1.0. So jruby -S gem install warbler today, try it out, and bring plenty of feedback to the JRuby user list!

Tags , , ,  | 17 comments

Comments

  1. Avatar Rich Manalang said about 2 hours later:

    Excellent. Looks good.

    One thing... is the servlet response available too (through rack)? I have this one line of code in our prod app:

    $javaservletresponse.send_error(499, “Oracle SSO”)

    I found out that there’s no way to send an error response in rails so I had to do it through the servlet response. Anyway, just wondering if jruby-rack provides a cleaner way of sending out this response.

    Rich

  2. Avatar Ezra Zygmuntowicz said about 2 hours later:

    Very cool Nick, thanks for working on this!

  3. Avatar Tom Brice said about 5 hours later:

    This is the best thing I’ve seen all year. Thank goodness for JavaOne! Wow. I’m dreaming of little merb-very-flat or camping apps deployed under a java app container.

  4. Avatar Nick said about 5 hours later:

    Rich: Does this work?

    render :text => "Oracle SSO", :status => 499
  5. Avatar Rich Manalang said about 6 hours later:

    @Nick, nope. Try it yourself... the HTTP head sig is different than the servlet error response.

  6. Avatar HGH said about 13 hours later:

    Very cool code..

    Thanks!

  7. Avatar Rich Manalang said about 20 hours later:

    @Nick, one thing I noticed... rack doesn’t seem to be picking up requests to the context root (i.e., “/” or “/myapp” if deployed to a relative context root) -- at least on oc4j. Once I add a relative path within the app it picks up the request, otherwise it thinks I’m trying to browse the directory. At first I thought it was the filter-mapping, so I changed from url-pattern:/* to *. That didn’t do it. I also played around with reordering the filter in web.xml -- above the listener and below the listener... nope.

    Anyway, I’ll take a look at your source and compare with goldspike to see if I can find out what’s going on. BTW, it does work on Jetty.

  8. Avatar Tyler Jennings said 1 day later:

    Congratulations Nick! I’m glad to see the jruby-rack:rails tag in there. We’ll certainly use it.

  9. Avatar Stephen Bannasch said 2 days later:
    Probably a buildr problem but I had facets 2.3.0 and 2.4.1 installed and couldn’t build rack (r159) until I deleted facets v2.4.1. rubygems.rb:140:in `activate’: can’t activate facets (= 2.3.0), already activated facets-2.4.1]
  10. Avatar Osman İzbat said 3 days later:

    Hi.

    I’m trying to run a simple rack application with jruby-rack:

    class HelloWorld def call(env) [200, {“Content-Type” => “text/plain”}, [“Hello world!”]] end end

    But i coulnd’t figure out how should i configure my web.xml and where to put hello.rb file that contains above code.

  11. Avatar Aslak Hellesøy said 3 days later:

    Thanks so much Nick! This couldn’t have come at a better time!

  12. Avatar ab5tract said 4 days later:

    Awesome, I was just complaining about the “lack of Rack” to the glassfish mailing list. No one responded though :(

    2 questions: 1) You do not mention Glassfish. How do they tie together? Is jruby-rack a replacement for goldspike? It seems strange to omit GF, since it looks very likely to become dominant in JRuby web app deployments. 2) Why is Warbler said to be for “wrapping a Rails app” in a .war? Why tie it to one framework? Is it secretly modular enough to .war other web apps?

    I just want a way for to deploy my Waves app without bothering with the mess. Thanks for bringing the community one step closer to achieving point-and-click Rack app deploys!

  13. Avatar Nick Sieger said 4 days later:

    @Rich: sounds like some differences in how OC4J and Glassfish handle getServletPath/getPathInfo/getRequestURI may be in play. Let’s work on it in IRC or on the mailing list.

    @Osman: I don’t have a simple Rack example out there right now. I’ll whip one up soon for you.

    @ab5tract: 1) This is not tied to Glassfish (or the GF v3 gem) specifically. It works off of the Java Servlet spec, so should work for any appserver. 2) Warbler is secretly able to war other apps as well, though I just barely introduced this functionality so I haven’t documented it yet. If you look in the newly generated config/warble.rb you might get a clue. The example I’ll work up for Osman should help for you too.

  14. Avatar kim said 5 days later:

    As awesome as this sounds, I cannot get it to work on neither tomcat or jetty using a rails app which deploys successfully using warbler 0.9.5 . Additionally, there’s no log output anywhere -- I just get the rails 500 page.

    I carefully revisited the new warble.rb options as well as web.xml.erb -- to no avail.

    Any hints on how to diagnose this?

  15. Avatar Nick said 5 days later:

    @kim: sorry to hear that. These are the kinds of bugs that obviously need to be fleshed out with wider use. Is there nothing in the tomcat logs/catalina.out file? If application initialization failed, there should definitely be something in it.

    Can you try dropping in this debug build? I’ve added a few extra exception rescue-and-dump clauses that should hopefully make things more visible. Drop this jar in place of the existing one.

    Also, for anyone who’s reading and has any more bug reports or feedback, please send them to the jruby-user list.

  16. Avatar Irfan Baig said 6 days later:

    I can confirm Rich’s problem in Resin too

  17. Avatar Otto Hilska said 14 days later:

    I’ve already got this working with JRuby + Merb + Glassfish. See http://blog.nodeta.fi/2008/05/22/living-on-the-edge-jruby-merb-glassfish/ for more information.