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.
Getting a Good View of Your Couch
So far I have been doing all my CouchDB queries using “temporary views” which are Javascript strings which are POSTed to the database and used to select the records you’re interested in. A more efficient way to do it is to save the Javascript strings as documents, these can be called with less traffic and a simpler API. “Permanent views” also create cached indexes, so they offer performance advantages over temporary views as well.
Tim Kofol took my ideas and ran with them, creating an ingenious way to maintain CouchDB views right in the Ruby code. Witness:
class Post < Blarg::CouchBase
couch_accessor :tags
couch_view :comments_view, %[
function(doc) {
if (doc.type "Comment") {
map(doc.post_id, doc);
}
}
]
couch_view :all_tags_view, %[
function(doc) {
if (doc.type ‘Post’) {
map(null, doc.tags);
}
}
]
def self.all_tags
self.all_tags_view.flatten.uniq.sort
end
def comments
comments = self.class.comments_view(:key => self.document_id)
comments.sort{|a,b| a.created_at <=> b.created_at}
end
end
With the views relevant to this class defined in the class itself, we need to load them into CouchDB. I added Rake task which finds all views defined in the project and loads them into CouchDB, creating them or replacing older versions.
rake db:views:load
Bring Selenium to the integration party
Running Selenium on a headless box. Not particularly complex, but amazingly useful for integration testing.
Do you wish you could leverage the power of Selenium? Do you long for it’s “automated web application UI tests”, but are boned by some headless horseman of a server? I have felt your pain. Tons of UI tests, but unable run them on the integration server. Ah, but there is a light at the end of the tunnel (that isn’t convincing the hosting company to attach a monitor)!
Here is the gist of it:
nohup Xvfb :4 -screen 0 1024x768x24 2>&1 > xvfb.log & sleep 3 # give Xvfb a few seconds to sort itself out DISPLAY=4 nohup java -jar selenium-server.jar 2>&1 > selenium.log &
Basically, Xvfb creates a virtual X session, without the need for those kludgey monitors and keyboards. The Selenium Remote Control server is started up with the newly created Xvfb display, that is the DISPLAY=4 part. That is that, the Selenium server is now running on the default 4444 port using Xvfb.
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:
Restore Finder magic to a sparsebundle directory
This is a quick fix to restore t he special behavior of a .sparsebundle directory in Finder.
While experimenting with TimeMachine’s unsupported network backup capabilities I rsync’d my host_blah.sparsebundle from one drive to another (without using -E, more on that later). The result was that my .sparsebundle now appeared in the Finder just as a normal folder, instead of with a disk image icon. This also meant that I couldn’t open the image in DiskUtility any more.
The fix is to use SetFile to restore the “Bundle” attribute.
$ /Developer/Tools/SetFile -a B host_blah.sparsebundle
The first time I mounted it afterwards I had to wait for fsck_hfs to complete, since the “com.apple.diskimages.fsck” attribute had been cleared, but otherwise it’s back to it’s old self.
First Post
What do we have here?
It would seem to be yet another blog, and it is. This one, however, is built with merb and CouchDB so building it gave me a chance to experiment with some interesting projects that I don’t get to use in my daily life as a professional web developer.
The code for this site is available to the many-eyes beasts of the Interwebs here:
git://sprocket.slackworks.com/srv/git/blarg.git
It requires merb and friends, as well as an instance of CouchDB to be running somewhere. There are a few reasons I chose merb over Rails (which is what I generally use professionally) to do this:
- It comes with no pre-packaged ORM. I wanted to use CouchDB, so none of the existing ORMs would really work for me. My previous experiences of trying to rip ActiveRecord out of Rails have been frustrating.
- It has more flexible routing than Rails. I realize there are ways to accomplish the things I’m doing here in Rails, but the merb routes seem clearer to me, less hand-wavy. And perhaps most importantly:
- It’s not Rails. I use Rails all day long, and I wanted to see what else is out there.
- About
- Technology, programming, the interwebs and other topics by members of the slackworks community.
- Recent
- Jul 23 2008 JNDI with Rails
- Jan 16 2008 Getting a Good View of Your Couch
- Jan 12 2008 Bring Selenium to the integration party
- Jan 12 2008 Bj Makes Attachment_fu Happy
- Jan 03 2008 Restore Finder magic to a sparsebundle directory
- Dec 18 2007 First Post
- Tags