Although I’m a massive fan of Rails, my background (and my professional life) is Java and Oracle. It was inevitable that I would try to bring these worlds together at some point. The following is a description of how I took and existing Rails 3 app, which was developed on SQLite and runs in production on MySQL, and got it to work on Weblogic 10.3.4.0 and Oracle 11g R2 database.
My application is a fairly standard Rails 3 web application, with 7 simple controllers and the appropriate resource actions. There’s a little bit of Ajax in the UI provided by JQuery. I’m currently running it on Rails 3.0.4 and using Bundler to manage my Gem dependencies.
My operating system of choice for this project was CentOS 5 (32 bit), running as a VirtualBox guest. CentOS is a derivative of Redhat and is the only truly open Enterprise Linux distribution. I manage my Ruby environment using RVM, using it to install both Ruby 1.9.2 and JRuby. I also installed OpenJDK 1.6 for my Java runtime environment.
To get started I took a clone of my application from my Git repository and made sure it ran against the SQLite locally using Ruby 1.9.2 and WEBrick. The only issue I had was getting SQLite 3.6.2 (which is the version required by the sqlite3-ruby gem) installed in CentOS. I temporarily added the ATrpms repository to my Yum config (see below) to get it in the end.
Set up repo file /etc/yum.repos.d/ATrpms.repo
name=Fedora Core $releasever - $basearch - ATrpms
$ sudo yum update
Next I ran the same application configuration under JRuby, just by using RVM to switch Ruby environments. I had to add the appropriate JDBC SQLite adapter gem to my bundler Gemfile. I discovered a nifty bundler trick using the “platforms” statement which let me configure gems based on my Ruby runtime environment.
Set up Gemfile In Rails app root directory
platforms :jruby do
gem 'activerecord-jdbcsqlite3-adapter', :group => [:development, :test]
Now that I had the app running under JRuby and was confident that my JRuby environment was properly configured, it was time to get it running against the Oracle database. My CentOS server has a regular install of Oracle 11g Enterprise Edition. You can download it from http://otn.oracle.com for evaluation purposes. You could also use the XE edition if you want the slightly less featured free version of Oracle. Either way, just download and follow the install instructions provided. The 11g R2 Enterprise Edition install was one of the simplest Oracle installs I have ever experienced.
With the database installed, I created a new Rails database environment in my application’s config/database.yml file. This way I could switch database environments just by changing the RAILS_ENV environment variable.
After creating the necessary database user and running the migrations I was able to run my application against the Oracle database under JRuby. The only issue I discovered was my use of the MySQL/SQLite keyword IFNULL in one piece of SQL. I was planning to create a simple IFNULL database function under Oracle (using NVL) to emulate the the MySQL/SQlite function (a wise man once told me it’s easy to make a more powerful system look like a less powerful one), but a little bit of Googling turned up the COALESCE function. I’ve been using Oracle for over 20 years but had never seen this. I was able to do a straight switch of the IFNULL function with COALESCE. Aren’t standards great.
Final step was to get the application running under the Oracle Weblogic Java EE server. I chose the Weblogic Development distribution to download and install from OTN. To install you basically unpack a zip file in the correct directory and run a few configuration scripts. All the info required was in the Weblogic README file. Once the Weblogic server was installed, I created a new Weblogic domain for my JRuby application using $WEBLOGIC_HOME /wlserver/common/bin/config.sh. Just fill out the form to create a new domain. Choose a suitable folder and name for your domain (I called mine “jrubydomain”) and be careful to get the right path to your Java environment. Once the domain is created you can start the server using the script automatically created in your domain’s root directory:
You can connect to the domain’s administration interface using your web browser and the URL http://localhost:7001/console (assuming you didn’t change any of the defaults). Use the username and password you defined during domain creation to log in.
To turn my Rails app into a Java EE app I used the excellent Gem, Warbler. Warbler is a set of Rake tasks that create a Java EE WAR file of your Rails app that can be deployed to a standard Java EE server. From your application’s root directory you type warble and a few seconds later you have a complete WAR file containing your app and all the dependent Gems. To deploy the WAR file you can go into the Weblogic domain administration interface and click the deployments link in the menu bar on the left. Then click install and follow the steps to upload your warbler created WAR file. Pay attention to the Context Root setting as this is needed to run your application, mine is set to /Expenses. To run and test my application I just pointed another browser window at http://localhost:7001/Expenses.
At this point I received the famous “Rails Application Failed To Start” page. Looking at the Weblogic server output I could see a problem with some class dependencies involving the Joda date/time library. I have to give credit and thanks to agardiner for working out the solution to this problem. (Full description here https://github.com/nicksieger/jruby-rack/issues/24)
“The issue occurs because WebLogic 10.3 includes an old version of Joda Time (version 1.2.1), which predates the addition of the withYear method on DateTime. This version is referenced in the manifest of the weblogic.jar file, and thus is higher in the classloader hierarchy than anything your web app references or includes, including JRuby.”
Fortunately he also proposed a simple solution that worked perfectly. Using a WEB-INF/weblogic.xml file it is possible to configure Weblogic to “give higher priority to any Java classes found in your WAR file, thereby ensuring that JRuby gets to use the bundled version of Joda Time.”
I created the following weblogic.xml file in my Rails application’s config directory.
The following entry is necessary to prevent Weblogics old version of the Joda time JAR (1.2.1) from taking precendence
over the much more recent version (1.6.0) included in JRuby.
Without this setting, Rails 3 will fail to start, due to the
missing withYear method on org.joda.time.DateTime.
To have Warbler include this weblogic.xml file correctly in your WAR file you need to create a warbler.rb config file in your application’s config directory. The easiest way to do this is let Warbler create a default file for you by typing:
$ warble config
Edit the warble.rb and add the following line:
# Files for WEB-INF directory (next to web.xml). This contains
# web.xml by default. If there is an .erb-File it will be processed
# with webxml-config. You may want to exclude this file via
# config.webinf_files += FileList["jboss-web.xml"]
config.webinf_files += FileList["config/weblogic.xml"]
Now run the warble command again to recreate your WAR file. This time it should include the new weblogic.xml file. Use the domain’s administration interface again to re-deploy the WAR file. At this point my application started up fine and I was able to successfully test it.