Wednesday, February 18, 2009

Simple Steps to Deploy a JRuby Rails application on JBoss 5

As part of the scheduled 0.9 version of Mobicents Sip Servlets, one of our tasks is to add telco features to JRuby on Rails applications so that it becomes quite easy to create click 2 dial or ipbx kind of apps in Rails.

Adhearsion, a framework written in Ruby by Jay Philips, allows Rails applications to control various functions in Asterisk servers.

Our goal here is a bit different we would like to enable current Rails application to leverage the Sip Servlets specification and be able to handle all the best parts of it. Not sure yet if we will try to integrate into JRuby-Rack or create a similar adapter for the Sip Servlets Specification... so stay tuned !

As I'm still a newbie on all the ruby world, feel free to comment to help us out or chime in with ideas on how to achieve this goal...

So since I'm a (J)Ruby-Rails-newbie, I started where all people start at the ruby home and documentation with their excellent tutorials. If you're a newbie as well please familiarize yourself with ruby before going farther. As my grandma said : "Learn to walk before you run!"

So after I felt like I grasped the basics of ruby I went on to play with the famous new kid in town that is getting all the hype these days (or is it already old fashionned and Scala, Haskell and such is getting the hype now ?) : Ruby on Rails. Same thing here, I followed their simple tutorial that gets you started and off I went with my first rails app. Then I wanted to get a bit farther and started with their blogging application tutorial.

I decided that this was enough for now and that I'll dig deeper as I go and since my objective was JRuby on Rails, I will retry to create the blogging app on JRuby.
So first download the JRuby version 1.1.6 and installed it in my home directory on my linux box under java/jruby-1.1.6. Set the JRUBY_HOME environment variable to the location where you installed it and add the JRUBY_HOME/bin directory to your PATH variable so that all commands are available from the command line. On linux this would be adding this to your ~/.bashrc file :

$ export JRUBY_HOME=/path/to/your/jruby/installation
$ export PATH=$PATH:$JRUBY_HOME/bin


You can test it out from the command line to issue the version by typing this
$ jruby -v

This will give the following output :
jruby 1.1.6 (ruby 1.8.6 patchlevel 114) (2008-12-17 rev 8388) [i386-java]
Ok let's install Rails now :
$ jruby -S gem install rails
This will produce the following output :
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Successfully installed activesupport-2.2.2
Successfully installed activerecord-2.2.2
Successfully installed actionpack-2.2.2
Successfully installed actionmailer-2.2.2
Successfully installed activeresource-2.2.2
Successfully installed rails-2.2.2
6 gems installed
Installing ri documentation for activesupport-2.2.2...
Installing ri documentation for activerecord-2.2.2...
Installing ri documentation for actionpack-2.2.2...
Installing ri documentation for actionmailer-2.2.2...
Installing ri documentation for activeresource-2.2.2...
Installing RDoc documentation for activesupport-2.2.2...
Installing RDoc documentation for activerecord-2.2.2...
Installing RDoc documentation for actionpack-2.2.2...
Installing RDoc documentation for actionmailer-2.2.2...
Installing RDoc documentation for activeresource-2.2.2...

Since JRuby doesn't support SQLite, we will use mySQL as the database (I assume it is already installed on your machine) so we install the jdbc mysql adapter for activerecord (if you don't know what activerecord, check the Rails documentation).
$ jruby -S gem install activerecord-jdbcmysql-adapter
This will produce the following output :
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Successfully installed activerecord-jdbc-adapter-0.9
Successfully installed jdbc-mysql-5.0.4
Successfully installed activerecord-jdbcmysql-adapter-0.9
3 gems installed
Installing ri documentation for activerecord-jdbc-adapter-0.9...
Installing ri documentation for jdbc-mysql-5.0.4...
Installing ri documentation for activerecord-jdbcmysql-adapter-0.9...
Installing RDoc documentation for activerecord-jdbc-adapter-0.9...
Installing RDoc documentation for jdbc-mysql-5.0.4...
Installing RDoc documentation for activerecord-jdbcmysql-adapter-0.9...
Let's create the blog application backed by mySQL now :
$ jruby -S rails blog -d mysql
Go into the “blog” directory, then modify the config/database.yml.
Adjust the adapter name, and instead of ‘mysql’ put ‘jdbcmysql’. You might also want to delete the lines starting with “socket:” or set it to tmp dir.

Here’s a simple example for the development environment:

development:
adapter: jdbcmysql
encoding: utf8
database: blog_development
pool: 5
username: root
password:
socket: /tmp/mysqld.sock
Also edit the config/environment.rb to specify the gem dependency we have on the jdbcmysql adapter (this step is mandatory for freezing the dependencies in your app later on)
Rails::Initializer.run do |config| 
...
config.gem "activerecord-jdbcmysql-adapter", :version => '0.9', :lib => 'active_record/connection_adapters/jdbcmysql_adapter'
...
end

Now, it’s time to create our database:
$ jruby -S rake db:create:all
The next step is to create some minimal scaffolding so that you could actually play with some dynamic functionality and database access:
$ jruby script/generate scaffold Post name:string title:string content:text
We need to update the database after that:
$ jruby -S rake db:migrate
Let's the application now :
$ jruby script/server
and go to http://localhost:3000/posts

Now let's freeze the rails version and the associated gems dependencies we are using into our application so that if rails or a dependency is upgraded in the system, our application will always use the version we freezed and not the newly upgraded version of rails from the system. Note: this is highly recommended for production env and really is a best practice (google freeze rails for more information)
Note that freezing is mandatory if you wish to deploy your application to JBoss 5 with the jboss-rails plugin.

It is a 2 steps process, first freeze rails then the dependencies (in our case the jdbcmysql adapter)
Here is the command to freeze your rails application :
$ jruby -S rake rails:freeze:gems
Here is the command
$ jruby -S rake gems:unpack:dependencies
You can verify that it worked by issuing this command
$ jruby -S rake gems
That will produce the following output :
 - [F] activerecord-jdbcmysql-adapter = 0.9
- [F] activerecord-jdbc-adapter = 0.9
- [F] jdbc-mysql = 5.0.4

I = Installed
F = Frozen
R = Framework (loaded before rails starts)

Ok now I can restart the app and play with again (nothing will have changed but if you modify your rails installation to a newer version the app will keep using the version you froze with it).

Let's deploy our application to JBoss 5 now :
First grab a JBoss AS 5.0.0.GA zip and unzip to the location of your choice then set the JBOSS_HOME env variable to it

Now let's get the jboss-rails plugin from the all too famous Bob McWhirter's github repo by issuing the following command (don't forget to move to another directory than your blog application) :
$ git clone git://github.com/bobmcwhirter/jboss-rails.git
from the newly created jboss-rails directory (note that JDK6 is needed for it to compile) :
$ mvn clean install
copy the content of the target/jboss-rails.deployer directory to JBOSS_HOME/server/default/deployers/jboss-rails.deployers.
Congratulations, We just installed the jboss-rails deployer into our jboss installation. Now let's tell the jboss deployers that we want to deploy a rails application by creating a blog-rails.yml file into JBOSS_HOME/server/default/deploy directory as explained by Bob that contain the following :
application:
RAILS_ROOT: /home/deruelle/ruby/rails/blog
RAILS_ENV: development
web:
context: /blog
host: *
ok we are all set up now, you can start your JBoss 5 application server :
$ cd JBOSS_HOME/bin
$ sh run.sh
and go to http://localhost:8080/blog/posts, there you go your JRuby-rails application working in jboss without the need to create a war and we are able to modify it at runtime, isn't that great !

Thanks Bob for you thesis, plugin and help !

Feel free to comment and let me know how well it worked for you !