Search code examples
javarubyscalajarjruby

How to package in a .jar java main + jruby compiled class + ruby script?


I am building a Spark application that make use of some feature already developed in Ruby.

I made the choice to invoke the Ruby part from my Scala main by defining MyProxy class in ruby and compiling with JRuby. I can then use MyProxy to invoke the rest of the Ruby code that stay in scripts. Foremost reason is that I was unable to compile them with JRuby, probably because they are too dynamic:

## myProxy.rb -> compiled into myProxy.class
## jrubyc --javac myProxy.rb
require 'java'
java_package 'ruby.proxy'

require_relative 'some.rb'

class MyProxy
  def self.invoke_script()
   ... ## invoke some other ruby in script that are note compiled by jrubyc
  end
end

and the Scala Main:

object myRun extends App {
  val something = MyProxy.invoke_script()
  ...
}

At runtime the flow looke like this:

Main.class (scala) -> call myProxy.class (compiled ruby of myProxy.rb) -> call function in script.rb

It works, and I was able to make a runnable jar for the Scala and compiled ruby part. But when I am running it: java -jar myApp.jar, it still need to access my myProxy.rb file and, of course, all other scrips.rb. So I need a copy of all my ruby scripts in the working directory when executing this command.

Ideally I would like to include all the ruby scripts in the myApp.jar as well, and be able to deploy easily deploy on a spark cluster. Is this possible, and how?

I have looked at warbler and rawr. However, I don't see how these tools can help me in this mixed environment (main in Java, some part compiled ruby, some part pure scripts).

Any help appreciated!


Solution

  • As stated in the jruby documentation, packaging ruby scripts in a jar, should be has simple as including them in the .jar (sic):

    Everything in the Java classpath is considered to be a load path entry, so .rb scripts, for example, contained in JAR files, are loadable.

    It wasn't working in my case, because I was using require_relative in my script, which doesn't seem to work properly in recent release of JRuby. Replacing require_relative with require made it works with scripts embedded in myApp.jar.

    Moreover using require_relative 'toto' in titi.rb was triggering an error of titi.rb script not found, which was misleading since it was titi.rb which was being executed.