Tutorial

How To Use JRuby to Run a Rails Application on Apache Tomcat 7 and Ubuntu 14.04

Published on November 14, 2014
How To Use JRuby to Run a Rails Application on Apache Tomcat 7 and Ubuntu 14.04

Introduction

Ruby on Rails (RoR) is a very popular framework that enables developers to quickly create web applications that adhere to modern design patterns. Using Rails, with just a few commands, you can build a production-ready vanilla CRUD (Create, Read, Update, Delete) application without having to write any code at all. Apache Phusion Passenger, Unicorn, and Puma are some of the popular servers which are used to run Rails applications.

The performance of Ruby MRI has improved considerably over the years. However, it is still slow compared to languages like Java or C. If you are interested in faster write times, which is necessary for critical, concurrent, distributed, and enterprise-grade applications, you should use JRuby instead, a Java implementation of Ruby.

Some Advantages of JRuby over Ruby MRI

Concurrency — Ruby MRI uses GIL (Global Interpreter Lock), and consequently has limited concurrency. JRuby, on the other hand, is able to use JVM’s threads, allowing you to achieve much higher levels of concurrency. This is usually the most important reason why JRuby is chosen over other Rubies.

Thread safety — Most of Ruby’s core classes are not thread-safe. Using such classes in multi-threaded applications is error-prone. JRuby is capable of using Java’s classes instead, which are designed for parallel processing.

More libraries — When you use JRuby, you have at your disposal not only a repertoire of Ruby gems but also all Java and Scala libraries. This lets you focus more on your application’s core functionality.

Ease of deployment — A JRuby on Rails application can be packaged into a single WAR file, which can be trivially deployed to any Java EE server. A lot of them even have browser-based interfaces to manage applications.

What This Tutorial Covers

In this tutorial you will learn to:

  • Create a simple CRUD application with Rails (one that uses Ruby MRI)
  • Convert our Ruby on Rails application to a JRuby on Rails application
  • Generate a WAR file for the application
  • Install Apache Tomcat 7
  • Deploy the WAR file to the Tomcat server

At the end of the tutorial, you’ll have a working JRuby on Rails application deployed.

Prerequisites

gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3

Follow that tutorial through the rvm requirements command.

Step 1 — Create a Simple CRUD RoR Application

Initialize RVM. This initialization is necessary for every new terminal you open.

. ~/.rvm/scripts/rvm

Note: If you already have a Rails application that uses Ruby 1.9.3, you can now skip to Step 2.

Create a directory to house all your Rails applications, and enter that directory.

mkdir ~/my_applications
cd ~/my_applications

We use Ruby 1.9.3 for this tutorial, because that is the latest version of Ruby that JRuby supports.

rvm install 1.9.3
rvm use 1.9.3

Install Rails.

gem install rails -N

Create a new Rails application, called simple.

rails new simple

Enter the application’s directory.

cd ~/my_applications/simple

Use nano to edit the Gemfile and uncomment the line for the gem therubyracer. This gem has to be added because our Rails application needs a JavaScript runtime.

nano ~/my_applications/simple/Gemfile

Ignoring the comments, your updated file should look like this:

source 'https://rubygems.org'

gem 'rails', '4.1.7'
gem 'sqlite3'
gem 'sass-rails', '~> 4.0.3'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.0.0'
gem 'therubyracer'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0',          group: :doc
gem 'spring',        group: :development

You’ll want to remove the , platforms: :ruby portion of the commented therubyracer line, because eventually we’ll be using JRuby rather than Ruby.

Install all the gems listed in the Gemfile.

bundle install

Add a few pages to the application using Rails’ scaffolding feature.

rails g scaffold Employee name:string age:integer address:text

The rails g scaffold command generates a few migrations. Apply them:

rake db:migrate

Change the root of the application to show the list of all employees. Use nano to edit ~/my_applications/simple/config/routes.rb and change its contents to what’s shown below, minus the comments:

Rails.application.routes.draw do
  resources :employees
  root 'employees#index'
end

Your Rails application that uses Ruby MRI is now ready. Run it on the development server by typing in:

rails s

This will take a minute or two to start up.

You can visit the application in your browser by visiting http://<server-IP>:3000. Create a couple of records to make sure everything is working as expected.

Application running on Ruby MRI WEBrick server

Return to your console, and stop the server by pressing Ctrl+C.

Step 2 — Install Java 8

In order to install and use JRuby, a JDK is required. Oracle JDK 8 can be installed using apt-get after adding the webupd8team/java PPA.

Add the repository by typing in the following:

sudo add-apt-repository ppa:webupd8team/java

Press Enter to accept the new repository.

Update apt-get’s package index files.

sudo apt-get update

Install Oracle JDK 8.

sudo apt-get install oracle-java8-installer

Note: You will be prompted to accept a license agreement before the actual installation begins.

Oracle's License Agreement Page

Select <Ok> and press Enter, then select <Yes> and press Enter.

After the installation is complete, run the command:

java -version

You should be able to see the following output, which means Java was installed correctly:

java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) Client VM (build 25.25-b02, mixed mode)

Step 3 — Install JRuby and JRuby on Rails

Use RVM to install and use JRuby.

rvm install jruby
rvm use jruby

The latest version of JRuby (1.7.16.1 as of November 2014) is now ready to be used. Check the version:

jruby -v

This shows you your server is using Oracle JDK 8. You should see output similar to this:

jruby 1.7.16.1 (1.9.3p392) 2014-10-28 4e93f31 on Java HotSpot(TM) Client VM 1.8.0_25-b17 +jit [linux-i386]

Install JRuby on Rails.

gem install rails -N

JRuby on Rails is now installed.

Step 4 — Configure the Application to Use JRuby

While a lot of Ruby MRI gems are supported by JRuby seamlessly, some gems that have native code aren’t. Most gems that are interfaces to databases fall into this category. Our application currently uses the sqlite3 gem, which is not supported by JRuby. activerecord-jdbcsqlite3-adapter should be used instead.

Similarly, JRuby uses therubyrhino instead of the therubyracer gem as a JavaScript engine.

Use nano to edit ~/my_applications/simple/Gemfile to make this change.

nano ~/my_applications/simple/Gemfile

Your file should look like this after updating the two lines, minus the comments:

source 'https://rubygems.org'

gem 'rails', '4.1.7'
gem 'activerecord-jdbcsqlite3-adapter'
gem 'sass-rails', '~> 4.0.3'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.0.0'
gem 'therubyrhino'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0',          group: :doc
gem 'spring',        group: :development

If you didn’t before, now you need to remove the platform setting from the therubyrhino line.

Some of our gems require native extensions. Type in the following to allow JRuby to support C extensions.

echo "cext.enabled=true" >> ~/.jrubyrc

You can now install the newly-added gems.

bundle install

If you are not using SQLite3 as a database, you might need one of these gems:

  • For Derby: activerecord-jdbcderby-adapter
  • For MySQL: activerecord-jdbcmysql-adapter
  • For Postgres: activerecord-jdbcpostgresql-adapter

Step 5 — Update Java’s Policy Files

Using a browser, download the JCE Unlimited Strength Jurisdiction policy files. You will have to accept Oracle’s License Agreement first.

(You can’t wget the files because you have to accept the agreement.)

On your local computer, upload the file to your server using scp:

scp Downloads/jce_policy-8.zip user@server-ip:~

On your server, install the unzip utility:

sudo apt-get install unzip

Unzip the file in a directory in /tmp.

cd /tmp
unzip ~/jce_policy-8.zip

Copy the policy files to the JRE’s lib/security directory.

cd /tmp/UnlimitedJCEPolicyJDK8
sudo cp *.jar /usr/lib/jvm/java-8-oracle/jre/lib/security/

Go back to your application’s directory.

cd ~/my_applications/simple

Execute the following command to speed up the JVM startup. This is necessary because virtual server environments tend to generate very little randomness on their own.

export JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom" 

At this point, our Rails application is fully configured to use JRuby. Start the development server:

rails s

This server might take several seconds to start. Wait till you see the following output before proceeding:

=> Booting WEBrick
=> Rails 4.1.7 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
=> Notice: server is listening on all interfaces (0.0.0.0). Consider using 127.0.0.1 (--binding option)
=> Ctrl-C to shutdown server
[2014-11-06 04:38:15] INFO  WEBrick 1.3.1
[2014-11-06 04:38:15] INFO  ruby 1.9.3 (2014-09-25) [java]
[2014-11-06 04:38:15] INFO  WEBrick::HTTPServer#start: pid=2620 port=3000

Use a browser to visit http://<server-ip>:3000 and test your application. Except for the fact that it is currently running on the JVM instead of using Ruby MRI, you should find nothing different about the application.

Return to the terminal and press Ctrl+C to stop the server.

Step 6 — Package the Application as a Deployable WAR File

To run the JRuby on Rails application on a servlet container like Tomcat, it should first be packaged into a WAR (Web application ARchive) file. This can be done using the warbler gem.

Install warbler.

gem install warbler

The SQLite database that our application uses is currently present in the application’s directory. When the WAR file is generated, the database in its current state will be placed inside the WAR file. We do not want this, because any changes that are made to the database after deployment will be overwritten if the application is redeployed.

Therefore, the SQLite database files should be moved to a location outside the application’s directory.

Create a new directory for the databases:

mkdir -p ~/databases/simple

In this tutorial, we are only concerned about the development database. Therefore, move the development database file to the newly-created directory:

mv ~/my_applications/simple/db/development.sqlite3 ~/databases/simple

Edit the database.yml file using nano.

nano ~/my_applications/simple/config/database.yml

Update the path of the development database. You can also remove the details for other environments, because you won’t be needing them for this tutorial. After the changes, your file should look like this:

default: &default
  adapter: sqlite3
  pool: 5
  timeout: 5000

development:
  <<: *default
  database: ~/databases/simple/development.sqlite3

Warbler also needs to know the Rails environment of the WAR. In this tutorial, we stick to the development environment. This is specified using a config/warble.rb file.

Use nano to create a new file named warble.rb

nano ~/my_applications/simple/config/warble.rb

Add the following to the file:

Warbler::Config.new do |config|
  config.webxml.rails.env = 'development'
end

Our application is now ready to be packaged into a WAR file. Run the following command to generate the file:

warble executable war

This will take a few moments.

Successful output should look like:

Downloading winstone-0.9.10-jenkins-43.jar
rm -f simple.war
Creating simple.war

At this point, there will be a file named simple.war in your application’s directory. Adding the argument executable to the command generates a WAR file that has a tiny embedded server (called Winstone) in it. This file can be used indepedently (without any external server) as follows:

java -jar simple.war

This is a good way to check for any problems with your WAR file. You can now use a browser to visit http://<server-ip>:8080. After a few minutes, you should be able see your application working correctly. All the entries you made in the database application earlier should be visible here.

You should wait until you see output similar to the following, to let you know that the server has started:

Nov 13, 2014 12:24:37 PM winstone.Logger logInternal
INFO: Started GET "/assets/application.js?body=1" for 108.29.37.206 at 2014-11-13 12:24:37 -0500

Return to the terminal, and press Ctrl+C to stop the embedded server.

Now that you have confirmed that the application is working as a WAR, generate a new WAR for Tomcat using the following command:

warble war

It will replace the old executable WAR with a new WAR file that doesn’t have any embedded server in it.

Step 7 — Install and Start Tomcat

Download the latest version of Tomcat.

cd ~
wget http://mirror.cc.columbia.edu/pub/software/apache/tomcat/tomcat-7/v7.0.56/bin/apache-tomcat-7.0.56.tar.gz

Create a new directory for Tomcat and enter that directory.

mkdir ~/Tomcat
cd ~/Tomcat

Extract the archive:

tar -xvzf ~/apache-tomcat-7.0.56.tar.gz

Set the maximum heap size available to Tomcat to 512m to avoid java.lang.OutOfMemoryError. This export has to be done every time you start the Tomcat server.

export CATALINA_OPTS="-Xmx512m"

As before, set the randomness generation:

export JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"

Start Tomcat:

~/Tomcat/apache-tomcat-7.0.56/bin/catalina.sh start

This server too takes several seconds to start. To monitor its logs, type in:

tail -f ~/Tomcat/apache-tomcat-7.0.56/logs/catalina.out

When the server is ready, you will see log messages like these:

Nov 10, 2014 4:12:32 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deployment of web application directory ~/Tomcat/apache-tomcat-7.0.56/webapps/manager has finished in 210 ms
Nov 10, 2014 4:12:32 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Nov 10, 2014 4:12:32 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Nov 10, 2014 4:12:32 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 3390 ms

Press Ctrl+C to end the tail command.

Tomcat is now installed and running. You can use a browser to visit http://<server-ip>:8080. You should be able to see Tomcat’s welcome page.

Apache Tomcat welcome page

Step 8 — Deploy the Application to Tomcat

To deploy a WAR to Tomcat, all you have to do is copy it to Tomcat’s webapps folder.

cp ~/my_applications/simple/simple.war ~/Tomcat/apache-tomcat-7.0.56/webapps

It might take a minute or so for your application to be automatically deployed. While you are waiting, you can monitor the contents of Tomcat’s log file using:

tail -f ~/Tomcat/apache-tomcat-7.0.56/logs/catalina.out

When your application is ready to be used, you will see log messages like these:

INFO: Deploying web application archive ~/Tomcat/apache-tomcat-7.0.56/webapps/simple.war
Oct 30, 2014 4:42:35 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deployment of web application archive ~/Tomcat/apache-tomcat-7.0.56/webapps/simple.war has finished in 47,131 ms

Press Ctrl+C to end the tail command.

You can now use a browser to visit http://<server-ip>:8080/simple/ and see your JRuby on Rails application running on Tomcat.

Restarting Your Session

If you disconnect from your SSH session at any time, you should run the following three commands:

cd ~/my_applications/simple
. ~/.rvm/scripts/rvm
rvm use jruby

And if you need to restart Tomcat, run the previous three commands, and make sure you set the two environment variables before starting the server:

export CATALINA_OPTS="-Xmx512m"
export JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"
~/Tomcat/apache-tomcat-7.0.56/bin/catalina.sh start

Conclusion

Thus, a Ruby on Rails application can be converted into a JRuby on Rails application with just a few configuration changes. JRuby on Rails applications can run on almost all servlet containers. In this tutorial, you have already seen how to run one on Apache Tomcat and Winstone.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Hathy A

author



Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
1 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Excellent Article! I was successfully able to implements on many system.But for few systems (Windowss 7) I am facing a issue. I follow all the steps till gem ‘activerecord-jdbcsqlite3-adapter’. After bundle install when I do rails s, I get below exception.

activerecord-jdbc-adapter is for use with JRuby only C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-jdbc-adapter-1 .3.20/lib/arjdbc/sqlite3/adapter.rb:1:in <top (required)>': undefined method 'load_java_part' for ArJdbc:Module (NoMethodError) from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-j dbc-adapter-1.3.20/lib/arjdbc/sqlite3.rb:2:in require’

Can you please help me out with this.This really critical

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel