Recently I worked with Krum to port a prototype we build on Ruby on Rails (RoR) to JPaaS using JRuby on Rails (JRoR). So today I’d like to share the process we used in the migrating. As we used this for prototyping only there are probably a lot of gaps and traps that you would need to fill and avoid for productive use. You have been warned!
ℹ Note: The commands and some of the tools are geared towards Mac as this is what I use. You should be able to follow the same steps on Windows using Cygwin as *NIX environment, but your milage may vary. This procedure is untested on Windows.
❗ Caveat: If you want to follow along with your own app make sure you have a backup of your current app and create a new branch in your git repository. You use version control, right? If not stop here and fix that first.
Goal #1: Keep your app runnable
In order to be able to identify if a problem arises due to the environment or changes we made to the app in the process we need to be able to switch back and forth between Ruby and JRuby as runtime. RVM the Ruby Version Manager allows us have multiple environments in parallel and have for example on terminal open to run the app on Ruby and another one for JRuby.
To get started we install RVM by executing the following in a terminal window. For more details and background information see https://rvm.io/
curl -L https://get.rvm.io | bash -s stable --ruby
This gives us the latest ruby version (1.9.3) as of this writing.
We can switch into the rvm environment with the following command:
Note: It’s a good practice to use gemsets to separate the dependencies of different apps in RVM. We won’t go there as we focus on one app, but you should read https://rvm.io/gemsets/
In order to manage all the gems we need for the different environments we use bundler and the Gemfile.
As we now entered a new Ruby environment you don’t have the gems available to you installed outside. So we need to install the gems first.
sudo gem install bundler bundle
The second command installs all gems that are listed in your Gemfile. If you are on a older rails version you might need to create the Gemfile first and do some prep work for bundler. See here: http://gembundler.com/rails23.html
Now we should be all set and your app should start as normal with
Goal #2: Make it run on jRuby
Now that we have the app running on RVM we can migrate it to jRuby. As a first step we need to setup a jRuby RVM which is very straight forward and simple.
rvm install jruby
Once the installation is done we switch into the jruby RVM. It’s best to do this is a new terminal window so you can keep the two environments up in parallel. Make sure you don’t confuse the two terminal though.
To keep the app working both on plain ruby and jruby we use the platforms feature of the Gemfile as outlined in the excerpt below.
... platforms :jruby do gem 'jruby-openssl' gem 'jruby-jars' gem 'jruby-openssl' gem 'jruby-rack' gem 'jdbc-maxdb', :git => 'https://github.com/SAP/cloud-jdbc-maxdb-gem.git' gem 'activerecord-maxdb-adapter', :git => 'https://github.com/SAP/activerecord-maxdb-adapter.git' gem 'activerecord-jdbc-adapter' group :development, :test do gem 'jdbc-sqlite3' gem 'warbler' gem 'activerecord-jdbcsqlite3-adapter' end end platforms :ruby do group :production do gem 'mysql' end group :development, :test do gem 'sqlite3' end end ...
Now we can try to install the gems in the jRuby RVM
sudo gem install bundler bundle
If there are errors because of other native gems that you missed move it into the platforms :ruby section and find a replacement that you then add to the platforms :jruby section of the Gemfile. Run bundle again and iterate until all errors are resolved.
Before we now start the app we need to adapt the database configuration in database.yml for the use of jdbc. Unfortunately I haven’t found a good way to keep this environment independent. One option might be to create additional entries like development_jruby and set the RAILS_ENV accordingly. For now I just comment the changed lines so I can switch back and forth easily. Let me know if you have a better solution.
development: # adapter: sqlite3 adapter: jdbcsqlite3 database: db/development.sqlite3 pool: 5 timeout: 5000
That’s it now you can start your application as usual with
Now that your app runs successfully on jruby RVM in development mode you can refer back to Krum’s blog for the required changes in the production environment to run it on JPaaS. With RVM you can skip the jruby -S prefix on all commands he lists with it.
Have fun and let me know if I missed some thing as this was a side project run over several month so minor details might have slipped.