Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

JRubyAndJavaCodeExamples

Thomas Yang edited this page · 10 revisions
Clone this wiki locally

» JRuby Project Wiki Home Page

JRuby and Java Code Examples

Below are some code examples showing how to call JRuby from Java and how to call Java from JRuby.

Table of Contents

JRuby calling Java

See also: Calling Java from JRuby

JRuby: call_java.rb

require "java"

java_import "java.util.TreeSet"
java_import "com.example.CallMe"
java_import "com.example.ISpeaker"

puts "Hello from ruby"
set = TreeSet.new
set.add "foo"
set.add "Bar"
set.add "baz"
set.each { |v| puts "value: #{v}" }

cm = CallMe.new
cm.hello
$globalCM.hello

class CallJava
  include ISpeaker
  def initialize
    super
    @count = 0
  end

  def say(msg)
    puts "Ruby saying #{msg}"
  end
  
  def addOne(from)
#    m.synchronize {
      @count += 1
      puts "Now got #@count from #{from}"
#    }
  end
end

Java: ISpeaker.java

package com.example;

public interface ISpeaker {
    public void say(String msg);
    
    public void addOne(String from);
}

Java: CallMe.java

package com.example;

public class CallMe {

    String mName;

    public CallMe() {
        this("Default");
    }
    
    public CallMe(String name) {
        mName = name;
    }
    
    public void hello() {
        System.out.println("Hello from "+mName);
    }
    
    public static void main(String []args) {
        System.out.println("Called main");
    }
}

Java calling JRuby

Java: CallRuby.java

package com.example;

import org.apache.bsf.BSFManager;
import org.apache.bsf.util.IOUtils;
import org.jruby.Ruby;
import org.jruby.javasupport.Java;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.javasupport.JavaUtil;
import org.jruby.runtime.Block;
import org.jruby.runtime.GlobalVariable;
import org.jruby.runtime.builtin.IRubyObject;

import java.io.FileReader;
import java.io.IOException;

/**
 * Example of how to:
 * 1. Use java objects in ruby
 * 2. Subclass/implement java objects in ruby
 * 3. Get ruby objects for use in java world
 * 4. Proxy ruby objects for normal use as java objects (interfaces/class)
 */
public class CallRuby {

    public static void main(String[] args) throws Exception {

        String dir = "/dclark/workspace/jrubytest/ruby/";

        double[] deltas = new double[3];
        for (int i = 0; i < 3; i++) {
            boolean useBSF = (i == 0);
            long start = System.currentTimeMillis();

            if (useBSF) {
                //--- Initialise ruby
                BSFManager.registerScriptingEngine("ruby", "org.jruby.javasupport.bsf.JRubyEngine", new String[]{"rb"});
                BSFManager manager = new BSFManager();

                //--- Define a global variable
                CallMe javaCallMe = new CallMe("globalCallMeInJava");
                manager.declareBean("globalCM", javaCallMe, javaCallMe.getClass());

                //--- Load a ruby file
                manager.exec("ruby", "call_java.rb", -1, -1, getFileContents(dir + "call_java.rb"));

                //--- Make a new ruby object
                String expr = "CallJava.new";
                ISpeaker ruby = (ISpeaker) manager.eval("ruby", "call_java.rb", -1, -1, expr);

                testMultiThreadsCallingRubyObject(ruby);

            } else {

                //--- Initialise ruby
                final Ruby runtime = Ruby.getDefaultInstance();

                // Need the blank object so can get a nice runtime for the Java.staticMethods calls
                runtime.eval(runtime.parse("require \"java\"\nclass BlankForJva\nend\n", "BlankForJva.rb", runtime.getCurrentContext().getCurrentScope(), 0));
                final IRubyObject blankRuby = runtime.evalScript("BlankForJva.new");

                //--- Define a global variable
                CallMe javaCallMe = new CallMe("globalCallMeInJava");
                IRubyObject globValue = JavaUtil.convertJavaToRuby(runtime, javaCallMe);

                // Wrap so that all methods are visible to ruby
                globValue = Java.java_to_ruby(blankRuby, globValue, Block.NULL_BLOCK);

                GlobalVariable globVar = new GlobalVariable(runtime, "$globalCM", globValue);
                runtime.defineVariable(globVar);

                //--- Load a ruby file
                runtime.eval(runtime.parse(getFileContents(dir + "call_java.rb"), "call_java.rb", runtime.getCurrentContext().getCurrentScope(), 0));

                //--- Make a new ruby object
                String expr = "CallJava.new";
                final IRubyObject rawRuby = runtime.evalScript(expr);
                ISpeaker ruby;
                if (i == 1) {
                    // Standard wrapper using Java Proxies
                    ruby = (ISpeaker) JavaEmbedUtils.rubyToJava(runtime, rawRuby, ISpeaker.class);
                } else {
                    // Or manually wrap ruby object so can be used as the interface (can optionally add synchronization as required on methods)
                    ruby = new ISpeaker() {
                        public void addOne(String from) {
                            //                            synchronized (rawRuby) {
                            rawRuby.callMethod(runtime.getCurrentContext(), "addOne", JavaUtil.convertJavaToRuby(runtime, from));
                            //                            }
                        }

                        public void say(String msg) {
                            rawRuby.callMethod(runtime.getCurrentContext(), "say", JavaUtil.convertJavaToRuby(runtime, msg));
                        }
                    };
                }
                testMultiThreadsCallingRubyObject(ruby);
            }
            long end = System.currentTimeMillis();
            deltas[i] = (end - start) / 1000.0;
        }

        for (int i = 0; i < deltas.length; i++) {
            System.out.println("Took " + deltas[i] + " on pass " + i);
        }
    }

    private static String getFileContents(String filename) throws IOException {
        FileReader in = new FileReader(filename);
        return IOUtils.getStringFromReader(in);
    }

    public static void testMultiThreadsCallingRubyObject(final ISpeaker ruby) throws InterruptedException {
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    ruby.addOne("t1");
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    ruby.addOne("t2");
                }
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        ruby.addOne("end");
    }
}
Note: If you have only simple interface requirements, you can use the second method of proxying the ruby object to include method level synchronization.

Note: BSF calling does not preserve ruby stack traces (add an error to a script and run both ways using the code above).

Something went wrong with that request. Please try again.