Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best approach to wrap an existing Java library in Ruby (JRuby)

Tags:

java

jruby

I'm looking to putting a ruby (JRuby) wrapper over a medium sized Java Library and am looking for advice and articles on best practices for everything from packaging to strategy.

I found a relatively dated (2009) discussion on this topic here: http://www.ruby-forum.com/topic/188447.

I'm looking to use the newest version of JRuby.

like image 246
justingordon Avatar asked Jan 25 '13 06:01

justingordon


2 Answers

I've written a few wrappers for Java libraries (Eurydice, HotBunnies, MessagePack, Rubydoop and Mikka, among others). Some of them are just JRuby code adapting the Java library, and some of them include Java code that interfaces with the JRuby runtime (MessagePack is in fact written completely in Java).

The thing that I've found is not solved very well is how to ship the JAR file for the Java library. You don't want to include it in the gem, because then you'll end up in JAR hell eventually. Common Java libraries like Netty will be bundled in many gems and eventually you will have gems that bundle incompatible versions. I've solved this problem by packaing gems that only contain the Java library JAR (see for example scala-library-jars and ning-compress-jars) and then having my wrapper depend on that gem. It's not a particularly scalable solution, but at least it will be more manageable than if you bundle JAR in the wrapper gem.

Your question isn't very clear on exactly what it is you want to know, I suggest you revise and be more specific. However, here are a few random things off the top of my head

  • A quick way of making a Java API more accessible to Ruby is to add methods to Java classes and interfaces. It's as easy as opening up a Ruby class (but Java interfaces are modules), and can make working with Java objects in Ruby much easier. These methods will only be seen by Ruby, they will not be visible to Java code.
  • Don't java_import into the global scope. It will cause lots of trouble for everyone. Remember that java_import isn't like import in Java where it's only local to the file, it's actually creating an alias in the scope. Wrap java_import and include_package in modules.
  • Don't use import -- it is incompatible with Rake.
like image 149
Theo Avatar answered Nov 08 '22 21:11

Theo


The wiki page: Scripting Java from JRuby (jruby 1.0+) contains excellent advice and ideas that you may leverage to get your wrapper

I think interesting the use of the Module name to scope access to the imported Java class

For Example: create a Ruby Module called JavaLangDemo that includes the classes in the Java package java.lang.

 module JavaLangDemo
   include_package "java.lang"
   # alternately, use the #import method
   import "java.lang"
 end

Now you can prefix the desired Java Class name with JavaLangDemo:: to access the included Classes:

 version = JavaLangDemo::System.getProperties["java.runtime.version"]
 => "1.5.0_13-b05-237"
 processors = JavaLangDemo::Runtime.getRuntime.availableProcessors
 => 2

The article also explains the following topics:

  • implementing a Java interface in Ruby
  • class name ambiguity between Java and Ruby
  • "mixing-in" more than one Java interface to a Jruby modules in JRuby
  • Exception Handling
  • Synchronization of objects for thread safety

and includes a list of usefull links to "Related Articles" for further information about Java integration layer

like image 3
Franco Rondini Avatar answered Nov 08 '22 21:11

Franco Rondini