Last month I visited a joint meeting for the Richmond Java User Group and Central Virginia Ruby Enthusiasts' Group. The audience was evenly split between Java and Ruby developers, which made for an ideal setting for my presentation about Java-Ruby interoperability that JRuby facilitates. On the tails of another great JRubyConf last week, I was inspired to share a summary of my presentation and my slides with interested folks who weren't able to attend the talk.
Using a Java library from Ruby
In this article, I'll focus on using a Java library from Ruby. You see, if you were to tinker with a single Java method, you would need to write a complete program with
“public static void main(String args)”. As we will demonstrate here, with JRuby IRB, it becomes almost trivial to play with Java methods.
We will use the unique Java library Akka here. According to the Akka website, “using the Actor Model together with Software Transactional Memory [Akka raises] the abstraction level and provides a better platform to build correct concurrent and scalable applications.”
The Akka Getting Started Tutorial
To begin, let us look at the Akka Getting Started Tutorial written in Java, and translate it into Ruby.
The example computes π using the Madhava-Leibniz series.
Note that in the series, the neighboring terms can be gathered into a smaller work unit without disturbing the identity, or other work units. We created a worker and a few additional workers that communicate by passing a message--Plain Old Java/Ruby Object with a little extra information--along with the message router acting as a broker.
Exploring the code
Now let us walk through the key points in the Ruby version.
Line 1: Enable Java integration support in JRuby.
Line 3: Add the lib directory (that resides in the same directory as the current file) to JRuby's library search paths.
Lines 8 through 16: Import the Java library's classes into the current namespace so we don't have to prefix them with Java::…. This is similar to Java's import statements.
Lines 18 through 25: This is a convenient method to create an Akka actor instance through the use of Ruby's Class.new, which is analogous to anonymous class declaration in Java. This greatly reduces the clutter when used on lines 81 and 125.
Lines 27 through 29: Define Plain Old Ruby Objects acting as messages between Akka actors. Note there is a lot less noise for these classes than there is for the Java counterparts.
Lines 31 through 59 define the Worker class. The part that actually performs the calculation
calculatePiFor is much more compact with the use of Enumerable#inject. When this actor is sent a message, it executes the methodonReceive.
Following the Java example, we are examining the class of the message passed; this is admittedly not characteristic of Ruby.
Lines 61 through 68 define the PiRouter class. Besides having an instance variable
:seq, there isn't much code, much of it is done in the Akka library itself.
Lines 70 through 116 define the Master class. Master responds to two kinds of messages. Calculate sets everything in motion. Result messages are sent from the PiRouter to the Master, which adds up the values of the Result messages until the set number of them were sent its way.
Lines 119 through 133 include the top-level class with one class method that sets up the concurrency latch and sends the Calculate message to the Master.
This example shows the basics of Java-Ruby interaction in a complete program. These fundamentals are applicable to your first explorations. If you come up with your own harmony of Java and Ruby, be sure to share it with us in the comments section.
Thank you, Richmond! (And beyond?)
I enjoyed sharing JRuby with the user group members I met in Virginia. Thanks again to the Richmond Java User Group and Central Virginia Ruby Enthusiasts' Group for hosting me. We are always excited to share JRuby with a larger audience and to hear your thoughts. If you are interested in arranging a JRuby presentation, drop us a line, and we'll chat!