By Joshua Moore
JRuby Series - Part 1
Introduction
This article is the first in a series of articles about JRuby and Rails. This first installment will cover the basics of getting started with JRuby: introduction, installation, and beginning to be comfortable with JRuby. We will wrap up with precautions and tips to make JRuby a dream to use.
Why should I care?
Before getting started, why choose JRuby? What does JRuby offer that the standard Ruby MRI does not? What will make it worth the time it takes to learn how to use it? Everyone’s answers to these questions will probably be a bit different in the same way that everyone has a different reason for using Rails. A whole article could be done on the topic of why to use JRuby; however, we only have time to consider 4 major reasons to use it in this article.
First, if you are already using Java™ there is no new production infrastructure that needs to be installed/setup. JRuby is packaged into the .war file so there are no outside dependencies. Simply use your existing application servers to host your Rails applications. This is especially useful in corporate environments where change comes only after long and hard fought battles.
Second, The Ruby MRI (version 1.8.x) is not able to take advantage of Rails being thread safe. JRuby on the other hand implements the Ruby threads as Javathreads, which are actually native threads. This allows JRuby to take full advantage of thread safe Rails right now.
Third is speed. JRuby is simply faster then any other Ruby interpreter except Ruby 1.9.1. Check out the Great Ruby Shootout: (http://antoniocangiano.com/2008/12/09/the-great-ruby-shootout-december-2008/) for more details. By using JRuby you can get a huge speed benefit without breaking your existing code or gem dependencies (not required to use the new Ruby 1.9.1 syntax).
Fourth, JRuby allows you to use Java in your ruby code. You can have Java code called directly from your ruby code. This allows you to pass objects back and forth between a Java application and a Ruby/Rails application without any serialization. Depending on your background or if you need to interact with a preexisting Java system this can be a great feature to have. As an added bonus JRuby even maps much of the Java syntax to mimic Ruby syntax.
These are just a few reasons for using JRuby. They are not all encompassing, but they are compelling enough to at least warrant looking into JRuby.
Words of caution
One pitfall in using JRuby is that it is not compatible with gems that have native extensions (i.e. the sqlite3 driver, hpricot, …). JRuby cannot execute the native extensions because it is executed on the Java Virtual Machine, unless the native code is called through the FFI (Foreign Function Invocation) interface. Starting with version 1.1.5 JRuby has implemented FFI. FFI is how Ruby-FFI and Rubinius invoke native functions. Any gem that calls the native code using the FFI interface can be used in JRuby (see http://blog.headius.com/2008/10/ffi-for-ruby-now-available.html for more details). Also, some gem developers maintain two version of there gem, one that works with JRuby and one that works with the Ruby MRI. If the gem does not use FFI and the author does not provide a JRuby version of the gem, then you will either need to find a pure Ruby alternative or use a Java library to replace the gem. Java code and libraries can be called from ruby code when it is run on JRuby.
If you cannot avoid using code with native extensions (that is not JRuby compatible) and you cannot find a replacement Java library then it is best to stick with the Ruby MRI.
Also you should be aware that automating the deployment process may require you to write your own Capistrano recipes. Because Capistrano is focused on deployment for Rails apps to Mongrel or Passenger there needs to be some custom recipes for JRuby Rails deployment. However, these changes should be minor and cause you little trouble.
Other then these two shortcomings I have found JRuby to be easy to use and I personally use it everyday in place of the Ruby MRI.
A bit of history
JRuby was started in 2001 by Jan Ame Petersen. After two years the project was taken over by Thomas Enebo. Under his lead, JRuby was switched from a Ruby 1.6 base to a Ruby 1.8 base. Later the project was joined by Charles Nutter who has helped significantly to bring JRuby where it is today. In addition to these people, the JRuby project has been worked on by many community members and its community is steadily growing. In the current release, this community has finished Ruby 1.8 compatible and is now working hard to improve the speed of JRuby and make it 1.9.1 compatible. JRuby is the first non-Ruby MRI interpreter to be actively working on support for Ruby 1.9.1 syntax.
Installing
The only requirement before installing JRuby is to install Java (see java.sun.com for instructions on installing Java on your computer.) JRuby requires the Java JDK 5 or 6 (1.4 may be compatible). JRuby is already fast, but I use JDK 6 which will make it run even faster. JRuby is available for automatic installation from these repositories MacPorts, Emerge, and apt-get. If your OS uses one of these three package management systems simply execute the following command:
MacPorts
sudo port install jruby
Emerge
sudo emerge jruby
apt-get
sudo apt-get install jruby
(warning: this is a very old version of jruby! I do not recommend using it)
I have no actual experience using Macports or Emerge so I do not know if they provide up-to-date versions of JRuby.
If your OS does not support one of these package management systems do not despair. It is easy to install JRuby from the zip/tar.gz file. This manual installation can be done on any supported platform (*Nix (including OSX), and Windows) by simply following these 3 easy steps.
1. Download JRuby from http://dist.codehaus.org/jruby/1.1.6/. The current stable version is 1.1.6, but this my have changed by the time that this goes to print. Make sure to get the latest stable version. Download the jruby-bin-1.1.6.zip or .tar.gz. Unless you want to personally review the source you do not need to download the complete or src files (jruby-complete-1.1.6 or jruby-src-1.1.6).
2. Unpack in the desired directory.
3. Add the JRuby bin directory to your systems path. For example, if JRuby is installed at c:\program files\jruby\ then add c:\program files\jruby\bin\ to your Windows system path. Review the documentation for your OS on how to add the bin directory to your system path.
That is all there is to it. JRuby should now be installed and running on your system. JRuby can be tested by simply opening a console and running this command jruby --version. JRuby should output something similar to this:
jruby 1.1.6 (ruby 1.8.6 patchlevel 114) (2008-12-17 rev 8388) [i386-java]
If there are any problems with the installation process or JRuby does not work as planned check out the installation wiki page (http://wiki.jruby.org/wiki/Getting_Started).
Getting your hands dirty
Now, JRuby is installed and working. But, how do you use it? In almost all respects it is exactly the same as using the regular Ruby MRI. Your code should run with absolutely no change needed. In order to run a ruby script simply type jruby script_file at the command prompt and you’re done. You have executed your first JRuby application (see example).
Script Example:
helloworld.rb
puts "hello world from JRuby"
#end file
jruby helloworld.rb
Output:
hello world from JRuby
Now, what about Ruby commands like gem, rake and rails? Executing the JRuby version of these commands is simple, just prefix the command with jruby –S (i.e. jruby -S gem install rails, jruby -S rake db:migrate, etc.). Other then the "jruby -S" at the beginning the commands are identical to there Ruby MRI counterparts.
* RubyGems (version 1.3.0), Rake, and Rspec come packaged with JRuby and are installed automatically with JRuby.
JRuby on Rails
Now, the section you have all been waiting for! JRuby on Rails. Does it work? The answer is that it works great! There is no need to worry about running your Rails app on the JRuby interpreter. The only thing that needs to be changed in your Rails app is the database.yml file. You must change the database configuration file because the normal ActiveRecord database drivers are not compatible with jruby as most of them contain native code. Instead of the normal ActiveRecord Drives JRuby uses a set of ActiveRecord drivers implemented on Java’s JDBC (Many thanks to Nick Sieger and all others who have worked on these drivers). All necessary Java libraries are installed with the ActiveRecord-JDBC gems, so there is no need to mess with any Java related code. Switching to the ActiveRecord-JDBC drivers is a simple 2-step process.
First, install the appropriate driver for your database.
ActiveRecord-JDBC drivers
MySQL
gem - activerecord-jdbcmysql-adapter
PostgreSQL
gem - activerecord-jdbcpostgresql-adapter
Oracle
gem - activerecord-jdbc-adapter
Microsoft SQL Server (missing change_column_default)
gem - activerecord-jdbc-adapter
DB2 (limited migration support)
gem - activerecord-jdbc-adapter
FireBird (missing change_column_default and rename_column)
gem - activerecord-jdbc-adapter
Derby (limited migration support)
gem - activerecord-jdbcderby-adapter
HSQLDB
gem - activerecord-jdbchsqldb-adapter
H2
gem - activerecord-jdbch2-adapter
SQLite3 (work in progress)
gem - activerecord-jdbcsqlite3-adapter
Informix (fairly complete)
gem - activerecord-jdbc-adapter
Once the correct driver is installed the second step is to modify the database.yml file. If you are using a database that has a specific database driver (not the generic activerecord-jdbc-adapter) then all you need to do is prefix the "adapter:" setting with "jdbc" (see example). See how quick and easy this is.
development:
adapter: jdbcmysql
encoding: utf8
database: notes_development
username: root
password:
If your current database does not have a specific driver (uses the activerecrod-jdbc-adapter driver instead), then you will need to add the URL and the Driver to the connection information. The URL and Driver are database specific so consult the documentation for the specific database's JDBC library. Here is an example of how your database.yml will look.
development:
adapter: jdbc
username: blog
password:
driver: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/weblog_development
Once the database driver has been changed it is business as usual when developing, running, and testing your Rails application. Just remember that whenever you execute one of the scripts in ./script/ directory prefix it with jruby. So start the WEBrick server with jruby ./script/server and get started!
If you do not want to use WEBrick the quickest alternative is to install the glassfish gem (jruby -S gem install glassfish). Once the glassfish gem is installed simply navigate to your rails directory and run jruby -S glassfish. The glassfish gem is not only easy enough to run as a development server it is also a fully featured and stable production server. I will write more about this topic, deployment options for JRuby, in a future article.
* All of the ActiveRecord-RDBC gems are hosted on github so you will need to add http://gems.github.com to your gem sources or add this option to your gem command
jruby -S gem --source http://gems.github.com install gem_name
Wrap up
By now (hopefully), you are able to install and use JRuby for your Ruby/Ruby on Rails development. For more information about JRuby, checkout the JRuby website at www.jruby.org. The wiki (hosted on the JRuby site) and the community provide great resources for those who are needing help or looking for more information about JRuby. Keep reading Rails Magazine and the next JRuby articles in this column.
Published in Issue #1: The Beginning
Back