Actually, I tried to get into JRuby few times, but truth to be told, I didn't see it at the level I needed it. However, recently, I gave it another try and it was the real deal - I am about to describe my experience below.
I've got a real Web application, which will be launched in production (soon), and it is using Ruby on Rails. So, I decided to port it into JRuby.
Here we go (I'll try to explain everything from the cleanest installation possible).
First step is, obviously, downloading JRuby. I am on Mac OS X, so everything will be according my experience on this platform. It should not be too different from any Unix-other one.
In my case I keep everything in /usr/local/, so let's install JRuby right there:
olexiy@airbus:~$ curl http://dist.codehaus.org/jruby/jruby-bin-1.1.6RC1.tar.gz -o ~/Downloads/jruby-bin-1.1.6RC1.tar.gz
olexiy@airbus:~$ cd /usr/local
olexiy@airbus:/usr/local$ sudo tar -zxvf ~/Downloads/jruby-bin-1.1.6RC1.tar.gz
olexiy@airbus:/usr/local$ sudo ln -sf jruby-1.1.6RC1/ jruby
Update paths:
olexiy@airbus:~$ cat .profile | grep JRUBY
JRUBY_HOME=/usr/local/jruby; export JRUBY_HOME;
PATH=$HTTPD_HOME/bin:$JAVA_HOME/bin:$JRUBY_HOME/bin:$SCALA_HOME/bin:$FLEX_HOME/bin:$MAVEN_HOME/bin:$MYSQL_HOME/bin:$MYSQL_HOME:/opt/local/bin:/usr/local/bin/bin:/usr/local/bin/lib:/usr/local/bin:/opt/bin:/usr/bin:/usr/sbin:/opt/local/bin:/usr/local/sbin:$PATH;
(and re-login to be sure your new paths picked up).
Let's install gem's now. I am specifying exact path where to use gem from, just because I want to be on the safe side as which gem will be launched. I need JRuby's one. Later down the text, I am specifying exact paths just to let reader understand easier which thing should have been running.
olexiy@airbus:~$ sudo /usr/local/jruby/bin/gem install rails mongrel jdbc-mysql activerecord activerecord-jdbcmysql-adapter rspec rack rake jruby-openssl activesupport
We'll need also ruby-debug, and need to install it with a tiny workaround:
olexiy@airbus:~$ cd /tmp
olexiy@airbus:/tmp$ curl http://files.rubyforge.vm.bytemark.co.uk/debug-commons/ruby-debug-base-0.10.3.1-java.gem -o ruby-debug-base-0.10.3.1-java.gem
olexiy@airbus:/tmp$ sudo /usr/local/jruby/bin/gem install ruby-debug-base-0.10.3.1-java.gem
olexiy@airbus:/tmp$ sudo /usr/local/jruby/bin/gem install --ignore-dependencies ruby-debug
olexiy@airbus:/tmp$ rm ruby-debug-base-0.10.3.1-java.gem
And we need to use MySQL Connector/J (we copy it into lib/ folder of JRuby):
olexiy@airbus:~$ cd /tmp
olexiy@airbus:/tmp$ curl http://mysql.easynet.be/Downloads/Connector-J/mysql-connector-java-5.1.7.tar.gz -o mysql-connector-java-5.1.7.tar.gz
olexiy@airbus:/tmp$ tar -zxvf mysql-connector-java-5.1.7.tar.gz
olexiy@airbus:/tmp$ sudo mv mysql-connector-java-5.1.7/mysql-connector-java-5.1.7-bin.jar /usr/local/jruby/lib/
olexiy@airbus:/tmp$ rm -R mysql-connector-java-5.1.7/ mysql-connector-java-5.1.7.tar.gz
Almost ready. Here is an example of what gems do I see installed for me:
olexiy@airbus:~$ sudo /usr/local/jruby/bin/gem list --local
*** LOCAL GEMS ***
actionmailer (2.2.2)
actionpack (2.2.2)
activerecord (2.2.2)
activerecord-jdbc-adapter (0.9)
activerecord-jdbcmysql-adapter (0.9)
activeresource (2.2.2)
activesupport (2.2.2)
columnize (0.3.0)
gem_plugin (0.2.3)
jdbc-mysql (5.0.4)
jruby-openssl (0.3)
mongrel (1.1.5)
rack (0.9.1)
rails (2.2.2)
rake (0.8.3)
rspec (1.1.12, 1.1.11)
ruby-debug (0.10.3)
ruby-debug-base (0.10.3.1)
sources (0.0.1)
Even if we are done with installation, we still need to prepare our Web application. Changes are required, but they are very easy. My application is called 'titi', and the changes we'll be making are not application-specific. You need to open config/environment.rb and after:
# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')
...
need to add the following block:
# Load JDBC drivers if we run on JRuby
if RUBY_PLATFORM =~ /java/
require 'rubygems'
RAILS_CONNECTION_ADAPTERS = %w(jdbc)
end
Also open config/database.yml and below is an example of changed settings for "development" (and all others will require similar changes):
...
development:
<% if RUBY_PLATFORM =~ /java/ %>
adapter: jdbcmysql
driver: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost/titi_development?user=root&password=
<% else %>
adapter: mysql
host: localhost
socket: /tmp/mysql.sock
<% end %>
encoding: utf8
database: titi_development
username: root
password:
...
It's all what's needed! Here we can launch us on JRuby (from you Web app folder):
olexiy@airbus:~/repo/titi/trunk/titi$ jruby -v
jruby 1.1.6RC1 (ruby 1.8.6 patchlevel 114) (2008-12-03 rev 8263) [i386-java]
olexiy@airbus:~/repo/titi/trunk/titi$ jruby script/server
Now, we can enjoy JVM. But important part is to be able to deploy for production on (say) Tomcat. And we need Warbler for that.
olexiy@airbus:~$ sudo /usr/local/jruby/bin/gem install warbler
Now, let's ask Warble to create us config file:
olexiy@airbus:~/repo/titi/trunk/titi$ sudo /usr/local/jruby/bin/warble config
It will be created in config/warble.rb and in my case I had to uncomment there the following lines:
...
config.gems += ["activerecord-jdbcmysql-adapter", "jruby-openssl"]
...
config.gems["rails"] = "2.2.2"
...
config.webxml.rails.env = ENV['RAILS_ENV'] || 'production'
...
Now, let's build the web application into WAR:
olexiy@airbus:~/repo/titi/trunk/titi$ sudo /usr/local/jruby/bin/warble war
Once done, we will have titi.war in the Web app folder. So let' go and have it running in Tomcat. Here is a short intro how to install it (if you didn't yet):
olexiy@airbus:~$ curl http://www.signal42.com/mirrors/apache/tomcat/tomcat-5/v5.5.27/bin/apache-tomcat-5.5.27.tar.gz -o ~/Downloads/apache-tomcat-5.5.27.tar.gz
olexiy@airbus:~$ curl http://apache.deathculture.net/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.tar.gz -o ~/Downloads/apache-tomcat-6.0.18.tar.gz
olexiy@airbus:~$ cd /usr/local
olexiy@airbus:/usr/local$ sudo tar -zxvf ~/Downloads/apache-tomcat-6.0.18.tar.gz
olexiy@airbus:/usr/local$ sudo ln -sf apache-tomcat-6.0.18/ tomcat
Let's not forget to update paths again to have Tomcat and Java there:
olexiy@airbus:~$ cat .profile | grep CATALINA
CATALINA_HOME=/usr/local/tomcat; export CATALINA_HOME;
PATH=$HTTPD_HOME/bin:$CATALINA_HOME/bin:$JAVA_HOME/bin:$JRUBY_HOME/bin:$SCALA_HOME/bin:$FLEX_HOME/bin:$MAVEN_HOME/bin:$MYSQL_HOME/bin:$MYSQL_HOME:/opt/local/bin:/usr/local/bin/bin:/usr/local/bin/lib:/usr/local/bin:/opt/bin:/usr/bin:/usr/sbin:/opt/local/bin:/usr/local/sbin:$PATH;
olexiy@airbus:~$ cat .profile | grep JAVA
JAVA_HOME=/usr; export JAVA_HOME;
PATH=$HTTPD_HOME/bin:$CATALINA_HOME/bin:$JAVA_HOME/bin:$JRUBY_HOME/bin:$SCALA_HOME/bin:$FLEX_HOME/bin:$MAVEN_HOME/bin:$MYSQL_HOME/bin:$MYSQL_HOME:/opt/local/bin:/usr/local/bin/bin:/usr/local/bin/lib:/usr/local/bin:/opt/bin:/usr/bin:/usr/sbin:/opt/local/bin:/usr/local/sbin:$PATH;
Ready to launch:
olexiy@airbus:~$ sudo /usr/local/tomcat/bin/catalina.sh start
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
olexiy@airbus:~$ ps -ax | grep tomcat
71464 ttys000 0:02.22 /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home/bin/java -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -classpath :/usr/local/tomcat/bin/bootstrap.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
71466 ttys000 0:00.00 grep tomcat
It's up an running. You can check it out on http://localhost:8080/. In other terminal window we will monitor logs while we'll deploy our application.
olexiy@airbus:~$ tail -f /usr/local/tomcat/logs/catalina.out
keep this window open while the deployment will be in process. To deploy our application we just need to copy titi.war into Tomcat's deployment directory.
olexiy@airbus:~/repo/titi/trunk/titi$ sudo cp titi.war /usr/local/tomcat/webapps/
Now, breath deeply for a minute or two, point browser to http://localhost:8080/titi/ and it gives me perfect production application running on Tomcat.
That's it! Very impressive how two different technologies were easy to mix together. They do require quite few steps, but it's all well worth it.

13 comments:
Thanks Alex, I followed your procedure. However I got error during tomcat6 start up
SEVERE: unable to create shared application instance
org.jruby.rack.RackInitializationException: Please install the jdbcmysql adapter: `gem install activerecord-jdbcmysql-adapter` (no such file to load -- active_record/connection_adapters/jdbcmysql_adapter)
Could you correct me if I did anything wrong to get this error.
Well done - worked for me just as advertised. Thanks alot!
Pravin,
I ran into that problem, but ended up getting it to work by completely removing jruby and ~/.gem then following Alex's steps exactly. I haven't isolated the problem, but it seemed to be caused by intermingling my local ~/.gem libs with the ones in /usr/local/jruby. Also be sure to manually clear out the unpacked war in tomcat (it can be slow doing it for you and you might unknowingly be running an old war), and delete everything in tmp in your rails project before running warble again.
Abditus@ -- you are correct with your note about war:clean - it helpful and lets you be on the safe side knowing it gets everything new.
pravin -- this may be the problem that warble didn't include this gem, and may be this gem was installed into your "other" gem tree - it is very easy to mess up when running couple Ruby's (and Java's and anything :-) on one machine. be sure you install all gems in one place, and that you update warble config to actually include this gem.
You also can do in some separate folder:
jar -xvf yourwebapp.war
and it will extract everything and you'll be able to see what is really coming in gems folder.
I hope this helps.
Thanks Abditus, and Olexiy.
I have problem with warble. Warble did not include the gems activerecord-jdbc-adapter-0.9, activerecord-jdbcmysql-adapter-0.9, jdbc-mysql-5.0.4, jruby-openssl-0.3, etc. while generating the WAR.
I had to copy these gems and gemspec manually to the tomcat's WEB-INF\gems folder.
I am not sure why warble missed these gems. However, Thanks for your help.
Did you try to change warble's config the way I mentioned in my blog post?
Yes Olexiy. I have warble.rb at \jruby-1.1.6RC1\bin\config\. My Project is \jruby-1.1.6RC1\samples\hello
I uncommented config.gems += ["activerecord-jdbcmysql-adapter", "jruby-openssl"], config.webxml.rails.env = ENV['RAILS_ENV'] || 'development', and config.gems["rails"] = "2.2.2"
Pravin --
I never got into this problem. It looks like still it's related to not having the gem in the right place. Try to install it again with jruby's gem and be sure it's installated into jruby's gem "folder". It should be included then.
What you also can try to do is to change jdbcmysql to just jdbc and see if it works for you. It seems that you are on Windows machine, and I really have no idea what exactly happens there. I didn't have any problems on Mac OS X and Debian.
I am working with Windows XP machine. I have warble at "C:\jruby-1.1.6RC1\bin". I have set PATH in command prompt for this bin folder. I have warble.rb at "C:\jruby-1.1.6RC1\bin\config\".
When I am running "warble" outside of jruby's bin folder, warble could not read warble.rb for the config.
Hey alex,
When u did sudo /usr/local/jruby/bin/gem install rails mongrel jdbc-mysql...
u install the mysql-connector-java-5.0.4-bin.jar in the gem path, so you dont need to download the driver :P
Great post !
That's right, though when I tried to deploy on two different Debians it didn't work there until I installed JAR manually the way I described. Didn't have time to dig into details, so it may be system configuration, but anyhow, I thought it would be better to mention it. :-)
Thanks for this!
Post a Comment