A couple of weeks ago I was visiting Sun Tech days conference held in Saint-Petersburg, Russia. One of sessions I attended was devoted to Java 6 SE Scripting API.

I must confess I like all that stuff about dynamic typing languages and what they bring to developers. I also like the whole idea about Ruby and enjoy a lot doing some Ruby programming.
So I decided to give it a try and integrate (for no reason) Java with Ruby.

You’ll need JRuby (at the time of writing the latest version 0.9.9) and a couple of things more. Please refer to this page for additional details.

Ah… as always, There Is More Than One Way To Do It (TIMTOWTDI) you can use Java 6 Scripting API or use JRuby API directly. I tried both but will mention just JRuby’s API. It’s pretty straightforward if you want to use Java6.

Ok… let’s see the code.
This is a Ruby script I have

    # script.rb
    def say_hi(name)
        "Hi from Ruby, #{name}!"
    end

Now I want to invoke this method from Java class just to see how it works.

    import org.jruby.*;
    import java.io.*;
    import org.apache.commons.io.FileUtils;

    public class JRubyTest {
        public static void main(String[] args) throws IOException {

            //getting content of Ruby script file
            String script = FileUtils.readFileToString(new File("script.rb"), "UTF-8");

            //instantiating Ruby runtime
            Ruby runtime = Ruby.getDefaultInstance();

            //executing script
            runtime.evalScript(script.toString());

              //invoking method
            Object res = runtime.evalScript("say_hi \"Java\"");
            System.out.println(res.toString());

        }
    }

As you can guess the result is

    Hi from Ruby, Java!

You can pass primitives and java.lang.String easily w/o any casting to Ruby’s method, but if you want to send back and forth Java reference types it’s harder and probably overcomplicated.
First you’ll need BSF (Bean Scripting framework).

The Bean Scripting Framework, when used with JRuby, will allow you to conveniently to pass your own Java objects to your JRuby script. You can then use these objects in JRuby, and changes will affect your Java program directly. To run a JRuby script using BSF, you must first copy the BSF.jar file into your /lib/ext/ folder.

Using Java from Ruby

Here you can find some tips how to use Java classes from Ruby.
My example is following:

    require "java"
    include_class 'java.util.ArrayList'
    array = ArrayList.new
    array.add("1234")
    array.add("123")
    array.add("12")
    array.add("1")

    def get_more_then(array, value)
      array.each{|item| puts item if item.size >= value }
    end

    get_more_then(array, 3)

Basically, what I’m doing is create a Java collection and iterate over it displaying its elements bigger than given number.

Even though you’re actually working with a Java Collection, it looks and feels (and quacks) like a regular Ruby collection object. All Java classes that implements java.util.Collection automatically gets an each method and includes Enumerable.

Hm… Not really. Actually, I wanted something different. My initial idea was a new array, so I had

    def get_more_then(array, value)
      array.map!{|item| item if item.size >= value }.compact
    end

But, of course there is no such methods as map and compact in Java Collection interface and they can not be mapped directly to Ruby’s methods.

Still, it’s pretty neat. I’m looking forward to try some Rails applications under JRuby. But wouldn’t use Ruby inside Java and vice versa yet. Both languages have their weak and strong sides you need just decide which one is more appropriate for concrete problem and use it.

Ruby gives me special feeling about programming which Java doesn’t and I hope I’ll use it more in future.

Advertisements