首先是一些背景知识:我有一个 Rails 2.2.2 应用程序,其中包含各种 janky 依赖项和自定义项,这使我暂时无法升级到 2.2.2 以上。当前计划是将此应用程序迁移到 JRuby (1.6.5),将其部署为 Tomcat (6.0.23 — 尚未绑定到此特定版本 FWIW) 中的战争,使用 warbler (1.3.2) 将其打包。
我想让应用程序的 JRuby 分支与原版应用程序有很大的不同,因为我不知道需要多长时间才能梳理和修复由运行时环境中的差异引起的所有问题。所以我希望能够继续干净、轻松地合并到来自香草应用程序的正在进行的工作中。
environments/*.rb
可以使用文件中设置的全局命名空间常量来配置应用程序中的许多自定义行为。但是可以通过使用 yaml 配置文件或设置 shell 环境变量来覆盖这些值;这主要是为了开发过程中的灵活性,不同的开发人员有时需要自定义各种设置。到目前为止,该系统运行良好,使我们的environments/development.rb
文件相对稳定且整洁,同时在我们进行黑客攻击时仍使我们能够对自定义进行大量控制。
我想在迁移到 JRuby 时保留这个定制系统。到目前为止,我正在使用自定义config/web.xml.erb
的方法将 yaml 文件中的相关环境变量和设置转换为<env-entry>
片段,从而使它们在初始化期间通过java:comp/env
JNDI 上下文可用。在更受限制的环境(如登台或生产)中,可以通过<Environment>
在容器context.xml
文件中包含override
属性设置为false
.
到现在为止还挺好。但是现在我正在努力将在初始化期间从 JNDI 上下文中检索到的值转换为全局命名空间常量。以下是相关位的摘录:
配置/环境/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
15 eval("%Q[ #{value_name} = '#{value}' ]")
16 end
网页.xml:
...
<env-entry>
<env-entry-name>FOO</env-entry-name>
<env-entry-value>bar</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>
...
catalina.out:
setting FOO to 'bar'
FOO is now 'fail'
当然,我希望最后一行是“FOO 现在是'bar'”。第 14 行lib/config_helper.rb
似乎是出了问题的地方。类似的代码在 vanilla ruby 中运行良好,但在 Tomcat 初始化期间它在这里不起作用。
那么,如何在 Tomcat 中的 Rails 初始化期间从 JNDI 环境条目中创建全局命名空间常量?