Making today worse so tomorrow seems better.

JNDI with Rails

I like to explain the relationship between Rails and Java is that Rails makes the things I hate doing easy and Java makes the things I like doing possible.

In this mind set, when using Rails on JRuby I want to do as little configuration in Java (XML sit-ups are bad) and leverage Rails as much as possible (a few yml stretches are good). The most common configuration cross over is the database connection. This is where JNDI helps out, now both sides can use the same connection pool.

Putting your ducks in a row

For the following examples to work, you will need the follow depedencies:

  • Sun’s JNDI File System Service Provider. Follow “Download JNDI 1.2.1 & More” to download File System Service Provider. You will need the fscontext and the providerutil jars both in you classpath. I would like to take this moment and say that Sun needs to get their head out of the mud and join the Maven party, instead of forcing people to navigate their cumbersome site.
  • Maven will make you hate less. Manually managing the cadre of jars that Java demands will just chalk you full of spite. While Maven does not alleviate the problem, it does put a purdy bow on it
  • A given, you must already have gone through the steps of setting up a JRuby runtime. Steps might be to strong of a word, basically it is unpackage and go.

Configuring Rails to create its own JNDI and Connection Pool

Now it is time to get the show on the road. The following setups will show how to startup a JNDI instance, register a Connection Pool, and then use the same Connection Pool in Rails and in a Spring

Setting up the database.yml

The latest version of activerecord-jdbc already supports using JNDI for connections. By setting additional information in database.yml, jndi_factory_initial and jndi_provider_url, a connection pool can be built and registered into JNDI. The jndi_factory_initial relates to the JNDI property java.naming.factory.initial, which boils down to the JNDI service that is going to be created. The jndi_provider_url relates to the JNDI property java.naming.provider.url, which is the URL to connect to the JNDI service. The standard setting, jndi, is going to be used as the location to store and retrieve the Connection Pool.

… more

Posted by Michael Guymon on Jul 23 2008 | Filed Under: jruby rails tech

JRuby Service in Rails

I have two worlds that need to collide. Rails solves the decade long problem of abusive Java web stacks and Java provides mature codebase to the Rails paradigm. JRuby has brought me the spark, now if I can only get the fire burning.

The problem: I need a Spring context to startup with Rails and use the config/database.yml.

The solution: A JRuby Service.

I want to expose tons of existing Java code and libs into Rails, but do not want to deal with a segmented world. Everything should be configured and started from one place, this is were a JRuby Service helps. The JRuby runtime will automatically load a class implementing a JRuby service interface (such as org.jruby.runtime.load.BasicLibraryService) when it is packaged in a specifically named jar at a specifically named placed.

Originally I was jumping though hoops trying to call static singletons, but ended up scratching my head how to get access to the Rails runtime. After finding hints from Ola Bini, with some searching and source diving, I found the javadoc for org.jruby.runtime.load.LoadService has the key. (An aside, it would be nice if the JRuby folks published the JavaDocs, even if it changed with every release).

Except from LoadService.java JavaDoc:

How to make a class that can get required by JRuby

First, decide on what name should be used to require the extension. In this purely hypothetical example, this name will be ‘active_record/connection_adapters/jdbc_adapter’. Then create the class name for this require-name, by looking at the guidelines above. Our class should be named active_record.connection_adapters.JdbcAdapterService, and implement one of the library-interfaces. The easiest one is BasicLibraryService, where you define the basicLoad-method, which will get called when your library should be loaded.

The next step is to either put your compiled class on JRuby’s classpath, or package the class/es inside a jar-file. To package into a jar-file, we first create the file, then rename it to jdbc_adapter.jar. Then we put this jar-file in the directory active_record/connection_adapters somewhere in JRuby’s load path.

The short and skinny of this? The package defines the directory and the class name determines the jar name. The package period separators are converted to slashes, so the package com.slackworks would be the directory com/slackworks. For brevity, this example uses the simple package slackworks, for a directory of slackworks. The class name, sans Service and converted from CamelCase to under scores determines the jar name. So the RailsSpringService class translates to rails_spring.jar

… more

Posted by Michael Guymon on Jul 06 2008 | Filed Under: jruby rails

Wildcard DNS and Rails

The most common Rails config wants a separate hostname for each application. If you tend to create new ones frequently, this can mean a lot of running back and forth to your DNS config. At best this means waiting for the changes to propagate, at worst it could mean waiting for corporate IT to get around to it.

Luckily, in addition to normal names, DNS allows you to create “wildcard” records that match any name not otherwise defined.

We setup each hostname with their own wildcard by default, so that foo.hostname is always an alias (CNAME) for hostname.

An example from our bind zone file:
sprocket                    IN      A               69.27.234.180
*.sprocket                  IN      CNAME           sprocket

This means that if I want to deploy my new app, The Awesomator, I can use the hostname ‘awesomator.sprocket.slackworks.com’ without having to change anything in DNS.

Then I drop my virtual host config awesomator.conf file, largely stolen from Coda Hale’s config , into Apache’s config directory (/etc/apache2/sites-available/ on Debian, /etc/httpd/conf.d/ on Red Hat). An Apache reload and a few mongrels later and I’m up and running on my new hostname.

… more

Posted by Nic Benders on May 16 2008 | Filed Under: rails infrastructure

Bj Makes Attachment_fu Happy

The attachment_fu plugin for Rails is great, and it’s support for S3 as a backend sounds really handy. Sadly tho ugh, it isn’t practical for anything other a demo or a proof-of-concept. Luckily its limitations can be worked around with the cunning use of Bj .

When you upload a file to a Rails app, your browser waits while Mongrel buffers the file, then your browser waits some more while Rails processes the fully uploaded file. Normally this “processing” is simply copying the file from where Mongrel put it to where Rails wants it, no big whup. The problem arises when this “processing” is substantially more time consuming, like, say transmitting the file to S3. There’s no guarantee that this will take place in a reasonable amount of time and meanwhile, not only is the user’s browser getting nearer to timing out, but that whole Rails instance is going to block and no one else can use it either. Rails is single threaded, remember?

The solution is to write the file to disk like normal, then spawn a process in the background to take care of uploading it to S3. This is where Bj comes in. Install thusly:

./script/plugin install http://codeforpeople.rubyforge.org/svn/rails/plugins/bj

./script/bj setup

rake db:migrate

Bj is a light weight work queue that uses your app’s database as a store. Requests are put into the bj_job table and run one at a time outside of the mongrel_rails process. Say we have a model UploadFile that uses attachment_fu:

… more

Posted by Jon Guymon on Jan 12 2008 | Filed Under: ruby rails tech programming