JDBC Connection Pooling for Rails on Glassfish
August 19, 2008
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
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:
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:
You’re done! Now all you have to do is build the WAR file and drop it in Glassfish’s autodeploy directory.