【发布时间】:2013-10-09 15:44:19
【问题描述】:
所以,我正在尝试将我的 JRuby on Rails 应用程序部署到 Tomcat 7。一切正常。
直到我尝试使用 Tomcat 的并行部署功能,它要求上下文/战争名称的格式为 name##VERSION.war。
当我第一次尝试在路径中要求一个带有## 的文件时,JRuby 对此感到窒息,并带有以下堆栈跟踪:
org.jruby.rack.RackInitializationException: no !/ in spec
from file:/opt/apache-tomcat-7.0.23/webapps/my-application##0001/WEB-INF/lib/jruby-rack-1.1.2.jar!/vendor/rack.rb:7:in `(root)'
from org/jruby/RubyKernel.java:1038:in `require'
from file:/opt/apache-tomcat-7.0.23/webapps/my-application##0001/WEB-INF/lib/jruby-rack-1.1.2.jar!/vendor/rack.rb:28:in `boot!'
from file:/opt/apache-tomcat-7.0.23/webapps/my-application##0001/WEB-INF/lib/jruby-rack-1.1.2.jar!/jruby/rack/boot/rack.rb:10:in `Rack'
from file:/opt/apache-tomcat-7.0.23/webapps/my-application##0001/WEB-INF/lib/jruby-rack-1.1.2.jar!/jruby/rack/boot/rack.rb:8:in `(root)'
from org/jruby/RubyKernel.java:1063:in `load'
from file:/opt/apache-tomcat-7.0.23/webapps/my-application##0001/WEB-INF/lib/jruby-rack-1.1.2.jar!/jruby/rack/boot/rack.rb:1:in `(root)'
at org.jruby.rack.DefaultRackApplicationFactory$4.init(DefaultRackApplicationFactory.java:206)
at org.jruby.rack.DefaultRackApplicationFactory.newErrorApplication(DefaultRackApplicationFactory.java:102)
at org.jruby.rack.DefaultRackApplicationFactory.getErrorApplication(DefaultRackApplicationFactory.java:66)
at org.jruby.rack.SharedRackApplicationFactory$1.call(SharedRackApplicationFactory.java:33)
at org.jruby.rack.AbstractRackDispatcher.process(AbstractRackDispatcher.java:30)
at org.jruby.rack.AbstractFilter.doFilter(AbstractFilter.java:31)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:298)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
正如堆栈跟踪所表明的那样,它似乎在要求上爆炸了。 JRuby 不能处理这种形式的路径吗?有什么办法可以解决这个问题,还是 JRuby 和 Tomcat 的命名约定之间存在根本冲突?
更新
我在 Tomcat 上附加了一个调试器,问题一直到 java.net.URL 解析 URL 字符串的方式:
new URL("jar:file:/opt/apache-tomcat-7.0.23/webapps/my-app##001/WEB-INF/lib/jruby-rack-1.1.2.jar!/vendor/rack-1.3.6/rack.rb")
这会引发 MalformedURLException。但是:
new URL("jar:file:/opt/apache-tomcat-7.0.23/webapps/my-app/WEB-INF/lib/jruby-rack-1.1.2.jar!/vendor/rack-1.3.6/rack.rb")
除了应用程序名称中的##001 之外,其他内容相同,并且可以正常工作。
顺便说一下,这些是在 JRuby 中的 org.jruby.runtime.load.LoadService 的第 1145 行调用的。
那么这有什么后果呢?好吧,一方面,如果 Tomcat 给 URL 解析带来麻烦,它看起来可能在它用来指示名称的字符上做出了一个考虑不周的选择。我不确定 JRuby 是否可以轻松解决这个问题。
有什么想法吗?
进一步更新
如果你的 URL 转义了哈希值,你就可以让它工作。 ## 变为 %23%23。不过,我认为这需要在 JRuby 本身中进行修补。
【问题讨论】:
-
更多证据表明问题出在 JRuby 层:如果我使用 WEBRick 在本地运行应用程序,一切正常。如果我将 gem 放在包含 ## 符号的目录中,事情就会中断。
-
你能用一个简单的脚本和一个 require 语句制作一个可重现的测试用例,缩小到 ## 问题吗?
-
嗯。它适用于最小的测试脚本。必须与 Tomcat 类加载器进行一些更复杂的交互。我会继续调查。
-
已提交关于 JRuby Jira 的错误报告:jira.codehaus.org/browse/JRUBY-6339
-
@levand - 如果您想将解决方案概括为您自己的答案,我将删除我的答案。 (请参阅meta.stackexchange.com/questions/90263/… 详细说明为什么这会有所帮助。)谢谢!
标签: ruby-on-rails tomcat jvm jruby warbler