3

So, I'm attempting to deploy my JRuby on Rails app to Tomcat 7. Everything works fine.

Until I tried using Tomcat's Parallel Deployment feature, which requires that the context/war name be of the form name##VERSION.war.

JRuby chokes on this the first time I try to require a file with a ## in the path, with the following stacktrace:

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)

As the stack trace indicates, it seems to be blowing up on the require. Can JRuby just not handle paths of this form? Is there any way I can get around this issue, or is it a fundamental conflict between JRuby and Tomcat's naming convention?

UPDATE

I attached a debugger to Tomcat, and the problem goes all the way down to the way java.net.URL parses URL strings:

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")

This blows up with a MalformedURLException. But:

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")

This is identical except for the ##001 in the application name, and it works fine.

These are invoked on line 1145 of org.jruby.runtime.load.LoadService in JRuby, by the way.

So what are the ramifications of this? Well, for one thing, it looks like Tomcat may have made a poorly considered choice in the characters it uses to indicate names, if it gives trouble to URL parsing. I'm not sure if JRuby can work around this easily.

Thoughts, anyone?

FURTHER UPDATE

You can make it work if you URL escape the hashes. ## becomes %23%23. This will need to be patched in JRuby itself, however, I think.

levand
  • 8,440
  • 3
  • 41
  • 54
  • More evidence for the problem being at the JRuby layer: If I run the app locally using WEBRick, everything works fine. If I put the gems in a directory including a ## symbol, things break. – levand Jan 11 '12 at 17:10
  • Can you make a reproducible test case that narrows down to the ## problem with just a simple script and a require statement? – Nick Sieger Jan 11 '12 at 19:25
  • Hm. It works in a minimal test script. Must be some more complex interaction with the Tomcat classloader. I'll keep investigating. – levand Jan 11 '12 at 20:53
  • 2
    Filed bug report on JRuby Jira: http://jira.codehaus.org/browse/JRUBY-6339 – levand Jan 12 '12 at 12:45
  • @levand - If you're game to recap the solution as your own answer, I'll delete my answer. (See http://meta.stackexchange.com/questions/90263/unanswered-question-answered-in-comments for elaboration of why this is helpful.) Thanks! – DreadPirateShawn Oct 09 '13 at 16:20

1 Answers1

1

Copying the answer from the comments in order to remove this question from the "Unanswered" filter:

You can make it work if you URL escape the hashes. ## becomes %23%23. This will need to be patched in JRuby itself, however, I think.

Filed bug report on JRuby Jira: http://jira.codehaus.org/browse/JRUBY-6339

~ answer per levand

Community
  • 1
  • 1
DreadPirateShawn
  • 8,164
  • 4
  • 49
  • 71