JDBC Connection Pooling for Rails on Glassfish
In Light Engineering (LED), we’re known to be multilingual – depending on the project, we’ve been known to speak Perl, Python, Java, C++, Javascript and PHP, to name a few. Our weapon of choice is still Ruby on Rails, the popular MVC framework. Out belief is that Rails makes certain types of tasks easy, and others laughably trivial. That being said, LinkedIn is still primarily a Java shop, and for good reason. Java technologies are mature, proven, and all around solid. For this reason, LED has had a very vested interest in the development work that is going into JRuby.
We started a few months ago around the time JRuby 1.1.2 went live by switching some of our Rails applications to run on Glassfish. Using Warbler, we successfully wrapped our Rails applications into WAR files and deployed on Glassfish (we’ll probably write a more detailed tutorial of this at a future date). A WAR file is completely self contained application that can be deployed simply by copying to an autodeploy directory. No more Apache/Nginx reverse proxy, no more Capistrano, no more installing gems on a production container, no more of any of that madness. This was a huge win, and we broke out the champagne bottles.
But we weren’t done. We weren’t taking advantage of many Java technologies, most notably, we weren’t taking advantage of the JDBC connection pooling capabilities of the Glassfish application server for our MySQL database.
We started by reading this tutorial by Arun Gupta of Sun. The article is fantastic, but the one criticism I have is that it was written from the perspective of a master Java engineer that learned Rails, as opposed to that of a Rails engineer approaching JRuby.
From a high level, here are the steps needed to enable JDBC connection pooling for a Rails application running in a Glassfish container:
- Define a JDBC connection pool.
- Define a JDBC resource with a JNDI name.
- Download and install the MySQL connection adapter.
- Update database.yml to use JDBC.
- Configure ActiveRecord to disconnect after every query.
Believe it or not, there are only five steps. I have to admit, I was initially intimidated. Java allows so much power and flexibility that, to a novice, seeing a hundred configuration choices in the Glassfish admin web UI can be a deterrent. As it turns out, we only need to touch two parts of that UI. Let’s get started:
1. Define a JDBC connection pool.
Log in to your Glassfish application server. Expand Resources->Connection Pools.
Click new. You’ll be presented with three fields. The name is arbitrary, but you’ll need to know it later. Select javax.sql.DataSource as the resource type, and MySQL as the vendor.
The next screen will have more options. Change the datasource classname to com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
Under additional properties, there should be fields configuring the database connection. Set these as appropriate.
2. Define a JDBC resource with a JNDI name.
JNDI stands for Java Naming and Directory Interface, and will allow us to create a standardized name for the JDBC connection pool we just created.
In the navigation pane, click through to Resources -> JDBC -> JDBC Resources. Click new.
In the drop down box, select the JDBC connection pool created in step 1. For the JNDI name, it’s accepted practice to name it jdbc/connection_name.
3. Download and install the MySQL connection adapter.
tar zxvf mysql-connector-java-VERSION.tar.gz
cd mysql-connector-java-VERSION
ant
cp mysql-connector-java-VERSION-bin.jar $GLASSFISH_HOME/lib
You may have to restart Glassfish for the install to work:
asadmin stop-domain DOMAIN
asadmin start-domain DOMAIN
4. Update database.yml to use JDBC.
In your config/database.yml file, we need to tell Rails to use the connection pool rather than directly connecting to the database. Here’s a snippet of our production configuration:
production:
adapter: jdbc
jndi: jdbc/polls
driver: com.mysql.jdbc.Driver
That’s all you will need. Unlike standard configuration files, you do not need to specify things like the username, password or host because these are configured in the Application Server. I like this method because it means the engineer doing the deployment does not need to build the YAML file each time, check it in to SVN, or copy from a database.yml template with the production settings. It’s one less deployment step, and ultimately, one less item on the security checklist.
5. Configure ActiveRecord to disconnect after every query.
ActiveRecord maintains a persistent connection to the database. This is no longer necessary, as there is very little overhead in opening a connection to JDBC, which manages the connection persistence. We’ll need to disable this. I’m using code borrowed from Nick Sieger’s awesome presentation at RailsConf 2008:
# config/initializers/close_connections.rb
if defined?($servlet_context)
require 'action_controller/dispatcher'
ActionController::Dispatcher.after_dispatch do
ActiveRecord::Base.clear_active_connections!
end
end
You’re done! Now all you have to do is build the WAR file and drop it in Glassfish’s autodeploy directory.
trackback
http://blog.linkedin.com/2008/08/19/jdbc-connection-pooling-for-rails-on-glassfish/trackback/







Arun Gupta August 19th, 2008
Ikai, Glad to know that the blog link helped. All the more exciting to know that you are using GlassFish for hosting your applications :)
Please suggest ideas for any content on my blog.
Alan Brown August 20th, 2008
Great writeup, Ikai. Definitely an essential piece for Ruby in the enterprise.
Loc Nguyen August 20th, 2008
It’s great to see LinkedIn investing time into new things! Your team must be accumulating a mountain of knowledge using and experimenting with this stuff in your production environments. Must be a fantastic place to work – any openings in LED? :)
Ikai Lan August 20th, 2008
Hi Loc, we’ve just filled out LED for the near future – but we’re always looking for great talent for our engineering division. The closest team to LED is probably Team Money, who works a lot with Groovy on Grails, an interesting relative of Ruby on Rails.
If you’re interested in looking at our available engineering positions, you can find them here. I’m happy to report that LinkedIn Engineering is one of those places that lives on the cutting edge. If you like diving into new technologies to complement the proven ones, you’ll be up to your neck in them here.
Brian Guan August 20th, 2008
Thanks Ikai.
Hi Loc, my group is definitely hiring. Check out this link:
http://www.linkedin.com/jobs?viewJob=&jobId=595885
Tom August 20th, 2008
I don’t understand why connection pooling is not an issue with Rails. I’ve searched the web and haven’t found a good answer. It appears an action controller keeps the connection active (unless you supply the code mentioned above). But where does the action controller initially get the connection? From a pool? or straight from the database?
Ikai Lan August 20th, 2008
Tom,
The connection is established by ActiveRecord::Base when the server boots up (railties/lib/initializers.rb). The connection itself can be retrieved with ActiveRecord::Base.connection. In the initialization step, the appropriate ActiveRecord adapter is loaded. In this example, the adapter is the JDBC adapter.
The reason Rails does not natively support connection pooling is because Rails is single-threaded, and therefore only really needs one connection per database. If each process has only one connection, there’s no need for a pool. In the example above, multiple separate Rails instances run inside a Glassfish container. Without connection pooling, N instances would create N connections.
Rails 2.2 is going to be interesting. The big feature coming is threaded Rails. I’ve heard talk of building connection pool management directly into Rails. I’m curious to see how this will play out with regards to JDBC pooling.
Tom August 21st, 2008
Thanks Ikai.
This post helps as well:
http://blog.headius.com/2008/08/qa-what-thread-safe-rails-means.html
“In a typical Mongrel setup, handling 10 concurrent requests means you have to have 10 copies of Rails loaded, 10 copies of your application loaded, 10 in-memory data caches, 10 database connections…everything has to be scaled in lock step for every additional request you want to handle concurrently.”
TUDBC August 27th, 2008
I ran a test which shows Java’s native connection pooling performance improvement varies (SQLServer improves +183% and MysQL only +24%) and it is actually not great at all compared to other pooling libraries. You can look at the stats on http://www.tudbc.org/performanceforwebapp
Gregory August 28th, 2008
Ikai,
Have you experimented with dedicating a DB connection to each JRuby instance, with no connection pooling at all? Assuming you periodically cycle the JRuby instances, and thus, periodically cycle your DB connections, it seems to me that you would get all of the same benefits. Or is it the case that DB connections need to be dropped and recreated more or less frequently than JRuby instances?
David P September 16th, 2008
Hi,
Is what are the performance difference between running a Rails app in Tomcat vs Glasshfish ? We are looking to deploy our first app under JRuby. I think that Glassfish would be a better solution, but I need “proof” :)
Andrea Minard January 22nd, 2009
Hello,
I am a recruiter employed with Follett Software Company and Follett Digital Resources http://www.fdr.follett.com (both educational technology businesses) in the Chicago, IL area. We are currently seeking a full time or contract-to-hire Senior PHP/Ruby on Rails developer due to the growth of our business. I have tried many sourcing/networking options to find this type of talented candidate, but it has been difficult. Do you have any ideas? We are willing to assist in relocating the selected candidate. Here is a link to the position. Any ideas would be greatly appreciated. Thank you.
http://www.follett.com/careers/showjobdesc.cfm?jobid=7363
Andrea Minard
Senior Recruiter