Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i use gems-in-a-jar with embedded JRuby?

I would like to use the excellent Sass as part of my build process. My build process is managed by Gradle. That means writing a plugin to run Sass. Sass is Ruby, and Gradle is in Groovy, but since Groovy runs on the JVM, i can use JRuby to run it, using the Java scripting API. Gradle scripts get dependencies in the form of jar files; i can get JRuby from Maven Central, but i will need to package Sass as a jar myself.

I've tried to follow Nick Sieger's gems-in-a-jar procedure for doing this, but have had no success. No matter what i do, i just can't get JRuby to pick up the Sass gem.

To isolate the problem, i have written a minimal Java (not Gradle) program which tries to use Sass via JRuby - i inventively call it JSass:

  • https://bitbucket.org/twic/jsass

There are two or three interesting bits. The first is the script generate-gem-jar.sh, which builds the gem jar:

gem install -i build/gems sass --no-rdoc --no-ri
jar cf lib/gemsass.jar -C build/gems .

The second is the so.demo.JSass class, which runs JRuby:

ScriptEngine rubyEngine = new ScriptEngineManager().getEngineByName("jruby");
ScriptContext context = rubyEngine.getContext();
context.setAttribute("inputFile", inputFile, ScriptContext.ENGINE_SCOPE);
String script = IOUtils.toString(JSass.class.getResourceAsStream("sassdriver.rb"));
rubyEngine.eval(script, context);

The third is the Ruby script which the main class tries to use to operate Sass:

require 'sass'
template = File.load(inputFile)
sass_engine = Sass::Engine.new(template)
output = sass_engine.render
puts output

The program is able to load the JRuby engine and execute the script, but it fails at require 'sass', saying:

LoadError: no such file to load -- sass
  require at org/jruby/RubyKernel.java:1033
   (root) at <script>:1
org.jruby.embed.EvalFailedException: (LoadError) no such file to load -- sass
    at org.jruby.embed.internal.EmbedEvalUnitImpl.run(EmbedEvalUnitImpl.java:132)
    at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:90)
    at so.demo.JSass.main(JSass.java:24)
Caused by: org.jruby.exceptions.RaiseException: (LoadError) no such file to load -- sass
Exception in thread "main" javax.script.ScriptException: org.jruby.exceptions.RaiseException: (LoadError) no such file to load -- sass
    at org.jruby.embed.jsr223.JRubyEngine.wrapException(JRubyEngine.java:115)
    at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:93)
    at so.demo.JSass.main(JSass.java:24)
Caused by: org.jruby.exceptions.RaiseException: (LoadError) no such file to load -- sass

What am i doing wrong?

like image 712
Tom Anderson Avatar asked Mar 23 '12 18:03

Tom Anderson


1 Answers

seems to me that it will only work as long as it is executed as a java -jar -rgems.jar you can make this work, you do not need to package it up in a .jar just take the sass-x.x.x directory (result of gem install sass) and store it in a known place and add it's lib directory to the $LOAD_PATH ... since you've built the jar already I would assume it being in a current working directory :

rubyEngine.eval("$LOAD_PATH << 'file://gemsass.jar!/gems/sass-3.1.15/lib'", context);

this needs to happen prior to your last line rubyEngine.eval(script, context);

if it's not in the jar it should be the same just specify the path e.g.

rubyEngine.eval("$LOAD_PATH << 'file:/home/42/gems/sass-3.1.15/lib'", context);

please note that this will only work if sass gems does not depend on other gems !

like image 135
kares Avatar answered Nov 19 '22 21:11

kares