Java/JSP + Ruby/Rails in a single webapp with JRuby
JRuby has been around for a little while, and is getting lots of attention for its ability to let Ruby developers code for a Java environment, and vice versa. However, as with many young projects, there isn't much documentation when it comes to the fringe cases.
The need I came across is the following: I have a client that's been running a JSP/servlet app under Tomcat for many years (originally started with JSP 0.91!). Over time I've added more and more functionality using the same JSP, Struts, etc. toolkits as everyone else uses. First up was a simple feature that involved sending some email notifications. It took me over an hour just to update the Strut-ified models (would've been even longer had I not used some Eclipse helpers), and another couple hours to add the business logic.
Just two weeks ago, I added this same functionality to a Rails app in about 30 minutes total (which included getting up to speed on ActionMailer)!
The client also needs a major piece of functionality added, which makes me shudder to think about having to code in Java. So I started looking into JRuby, and how it could let me add these features via Rails without changing the existing codebase. There's an add-on piece of code via goldspike/rails-integration that will let you package a rails app into a WAR file for deployment to any Java container. However, this (and all related posts and documentation) seems to assume you're just packaging a Rails-only app. I wanted to blend some new Rails functionality into my existing WAR. It took a few hours to work my way through the code, but finally came up with the following solution.
First, the Java web.xml needs the following stanzas added (make sure they get added in the correct order per the Servlet DTD):
<code> <context-param> <param-name>rails.env</param-name> <param-value>development</param-value> </context-param> <servlet> <servlet-name>rails</servlet-name> <servlet-class>org.jruby.webapp.RailsServlet</servlet-class> <init-param> <param-name>rails.root</param-name> <param-value>/web/tomcat/webapps/jspapp/railsapp</param-value> </init-param> </servlet> </code>
Next, the following line needs to be added to the environment.rb in your rails app:
<code> ActionController::AbstractRequest.relative_url_root = "/jspapp/railsapp" </code>
And then finally, to make sure the rails app code (outside of public) is not exposed, (assuming you're using Apache) add the following security controls to your front-end server:
<code> <Directory "/web/tomcat/webapps/jspapp/railsapp"> Order deny, allow Deny from all </Directory> <Directory "/web/tomcat/webapps/jspapp/railsapp/public"> Order allow, deny Allow from all </Directory> </code>
Now you've got a blended webapp that lets you use Java or Rails in a seamless fashion!

Comments
Any one have the sample war ?
Any one have the sample war ?
Hi Greg, I am trying to
Hi Greg,
I am trying to download sample.war one you have posted but i am unable to do that...can you just help me out
Thnx
Rails' complaint about the
Rails' complaint about the stylesheet indicates it doesn't know the url root setting. Is this set in RAILS/config/environment.rb:
ActionController::AbstractRequest.relative_url_root = \
"/sample/railsapp"
Also, try adding this to your web.xml (i.e., give the context-relative path, not the absolute filesystem path):
rails.root
/sample/railsapp
and take out the corresponding init-param block under the servlet stanza.
Right now I'm just using
Right now I'm just using tomcat.
Here is what is in the railsapp/log/development.log file:
# Logfile created on Sun Dec 16 10:53:30 CST 2007 by /
Processing ApplicationController#index (for 127.0.0.1 at 2007-12-16 10:53:31) [GET]
Session ID: 3e55f740ccab4822715dae6bedad0e3e
Parameters: {}
ActionController::RoutingError (no route found to match "/stylesheets/styles.css" with {:method=>:get}):
D:/tomcat/apache-tomcat-5.5.25/webapps/sample/WEB-INF/gems/gems/actionpack-1.13.3/lib/action_controller/routing.rb:1292:in `recognize_path'
D:/tomcat/apache-tomcat-5.5.25/webapps/sample/WEB-INF/gems/gems/actionpack-1.13.3/lib/action_controller/routing.rb:1282:in `recognize'
D:/tomcat/apache-tomcat-5.5.25/webapps/sample/WEB-INF/gems/gems/rails-1.2.3/lib/dispatcher.rb:40:in `dispatch'
:0
Rendering D:/tomcat/apache-tomcat-5.5.25/webapps/sample/WEB-INF/gems/gems/actionpack-1.13.3/lib/action_controller/templates/rescues/layout.rhtml (404 Page Not Found)
On the other hand, I think the error message is coming from Tomcat. Here's what I'm getting:
Apache Tomcat/5.5.25 - Error report
HTTP Status 404 - /sample/railsapp/
type Status report
message /sample/railsapp/
description The requested resource (/sample/railsapp/) is not available.
Apache Tomcat/5.5.25
Kip - Are you using just
Kip - Are you using just Tomcat, or is IIS or Apache in front of it? Can you tell if you're getting the 404 from Tomcat or Rails? Check the logs/ folders under D:/tomcat/apache-tomcat-5.5.25/logs and D:/tomcat/apache-tomcat-5.5.25/webapps/sample/railsapp/log. I had it working on my XP laptop, so it is possible.
Hi Greg, Great post. I tried
Hi Greg,
Great post. I tried your sample and the app comes up fine, but but when I click on the "Jump to the Rails app" link I get a 404 error.
I'm trying to do this on Window XP so maybe that is the root of my problem. I have the following in my web.xml:
D:/tomcat/apache-tomcat-5.5.25/webapps/sample/railsapp
Any thots?
Regards.
I've posted a sample.war
I've posted a sample.war that contains everything to show off a working JSP & Rails app. Unfortunately I don't yet know how to make it all transparent for the war, so you'll need to edit the web.xml to give the correct path. I've marked each spot with CHANGEME to indicate where you need to make the edits.
great idea, i'll post one
great idea, i'll post one shortly.
hi there, looks cool. do
hi there,
looks cool. do you have a WAR (and its source ) of such a HelloWorld (or petstore) to share with people ?
thank you,
BR,
~A
Post new comment