views:

382

answers:

2

Hi all, I am trying to write some code in ruby (using jruby) to be compiled to java bytecode with jrubyc and deployed to a remote machine where it will be run on the JVM (no ruby available there).

Everything works fine as long as I am happy to stick with the standard jruby library. As explained on the jruby website, I simply copy the jruby-complete.jar library to the remote machine and include it in the classpath at runtime. I fire my compiled script and it works: cool!

The problems start when I need some other libraries (typically rubygems) to run my script.
I am aware of cool stuff like rawr, -which I successfully tested- to put together all you need in a single package. However that is not the solution I am looking for: I will have many small scripts to run independently and I don't want each of them to grow to at least 10 MB just because I insanely include the jruby-complete.jar in each of them.

What I would like is to compile a .jar for each of the libraries that I will need to use, put all of them in a common folder on the remote machine and include them at runtime in the classpath when I run my compiled jruby scripts on the JVM.
This said, I tried to follow the instructions here: http://blog.nicksieger.com/articles/2009/01/10/jruby-1-1-6-gems-in-a-jar
I tried exactly the example shown there, with the "chronic" gem. Going step by step:

  1. Install the gem locally: java -jar jruby-complete-1.1.6.jar -S gem install -i ./chronic chronic --no-rdoc --no-ri
  2. Package it into a jar: jar cf chronic.jar -C chronic .
  3. Write a two lines test script, saving it as testt.rb:

    require 'chronic'
    Chronic.parse('tomorrow')

  4. Compile with: jrubyc testt.rb

  5. Run the resulting java class testt.class with the following (having both jruby-complete.jar and chronic.jar in the same folder as the java class): java -cp .:/jruby-complete.jar:./chronic.jar testt

I get the following error:

Exception in thread "main" file:/Users/ave2/NetBeansProjects/jrubywatir/lib/jruby-complete.jar!/METAINF/jruby.home/lib/ruby/site_ruby/shared/builtin/core_ext/symbol.rb:1:in `const_missing': uninitialized constant Chronic (NameError)
from testt.rb:2
...internal jruby stack elided...
from Module.const_missing(testt.rb:2)
from (unknown).(unknown)(:1)

I really don't understand what I am doing wrong, and I am totally stuck on this. I am a noob in Ruby, much more used to Python: don't miss a chance to convert an infidel! :-) Thanks.

A: 

Put this at the top of your test script:

require 'rubygems'

Rob
Rob, thanks for your answer. I added the line and compiled again, but still getting an error, though slightly different (says something about a custom require):java -cp .:./jruby-complete.jar:./chronic.jar testtException in thread "main" file:/Users/ave2/NetBeansProjects/jrubywatir/lib/jruby-complete.jar!/META-INF/jruby.home/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `const_missing': uninitialized constant Chronic (NameError) from testt.rb:3 ...internal jruby stack elided... from Module.const_missing(testt.rb:3) from (unknown).(unknown)(:1)
antonio
A: 

From what I can tell, it looks like you're not doing anything wrong, and you've probably hit a bug. Can you try your example with a more recent release (http://jruby.org/download) and if you still see the issue, create a bug at http://bugs.jruby.org/ ? Thanks.

Nick Sieger
Hi I just found the solution, which is maybe kind of obvious for people with at least some ruby skills. However it is still worth mentioning it somewhere for noobs like me. Here it is:when you create your jar file it MUST NOT have the same base name as the gem you want to load. In my case I had my jar file called "chronic.jar" and it did not work. I simply renamed it to "chroniclib.jar", added the require 'rubygems'in my script, compiled it and ran it with: java -cp .:./jruby-complete-1.4.0.jar:.chroniclib.jar testtIt works! No need to require the .jar inside the script! Jruby rocks! :-)
antonio
By the way, Nick, thx for your great post on Gems-in-a-jar without which all this would have never been possible!
antonio
One last thing: the issue exists for me only if the .jar and the script are in the same folder. If i put the jar into a subfolder and adjust the java classpath accordingly it works even if the jar has the same name as the gem
antonio