First some background: I’ve got a Rails 2.2.2 app with all kinds of
janky dependencies and customizations that keep me from upgrading past
2.2.2 for the moment. Current plan is to migrate this app to JRuby
(1.6.5), deploying it as a war in Tomcat (6.0.23—not yet tied to this
particular version FWIW), using warbler (1.3.2) to package it up.
I want to prevent the JRuby branch of the app from diverging
substantially from the vanilla app since I don’t know how long it’s
going to take to tease out and fix all of the issues caused by
discrepancies in the runtime environments. In the mean time, I want to
be able to continue to cleanly and easily merge in ongoing work from the
vanilla app.
A number of customized behaviors in the app can be configured with
globally namespaced CONSTANTs set in the environments/*.rb files. But
these values can be overridden by using a yaml configuration file or
setting a shell environment variable; this is primarily for flexibility
during development, where different devs somtimes need to customize
various settings. This system has worked well so far, leaving our
environments/development.rb file relatively uncontested and uncluttered
while still giving us a great deal of control over customization as
we’re hacking.
I would like to preserve this system of customization in the move to
JRuby. So far, I’m using a customized config/web.xml.erb
that converts
relevant environment variables and settings from the yaml file into
fragments, which makes them available during initialization
via the java:comp/env
JNDI context. In more restricted environments
(like staging or production), many of these settings can be locked down
by including corresponding settings in the container’s
context.xml
file with the override
attribute set to ‘false’ (I
haven’t actually tested this part yet, but the documenation suggests it
should work).
So far, so good. But now I am struggling to turn the values retrieved
from the JNDI context into global namespace CONSTANTs during
initialization. Here are excerpts of the relevant files:
config/environments/developer.rb
:
…
envset “FOO”, “baz”
FOO=“fail” unless defined? FOO
printf “FOO is now ‘%s’\n”, FOO
…
lib/config_helper.rb
:
1 include Java
2 import javax.naming.InitialContext
3 import javax.naming.NameNotFoundException
4
5 ctx = InitialContext.new
6
7 def envset(value_name, default_value)
8 value = nil
9 begin
10 value = ctx.lookup(“java:comp/env/#{value_name}”)
11 rescue NameNotFoundException => e
12 value = default_value
13 end
14 printf “setting %s to ‘%s’\n”, value_name, value
14 eval("%Q[ #{value_name} = ‘#{value}’ ]")
15 end
web.xml
:
…
FOO
bar
java.lang.String
…
catalina.out
:
setting FOO to ‘bar’
FOO is now ‘fail’
Where this last line should be “FOO is now ‘bar’”, of course. Line 14 of
lib/config_helper.rb
seems to be where things are going wrong. Similar
code has worked fine in vanilla ruby, but it doesn’t work here during
initialization in Tomcat. What am I missing? And if there is a better
way to do this than eval(), I’d welcome it. (Any niggly style, design,
or best-practices recommendations welcome, too).
Also, if there is a better forum for this question, please let me know.