// See referring document/blog from Yoko Harada: // http://yokolet.blogspot.com/2008/03/tips-for-jruby-engine-how-to-refer.htm package klauer.callingruby.yokoharada; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; /** * From Yoko Harada's blog. * See http://yokolet.blogspot.com/2008/03/tips-for-jruby-engine-how-to-refer.htm for more information * on how he has constructed this class. * This class outlines how you use the jruby-engine.jar and Java 6 JSR233 Scripting * API to retrieve a script engine instance and use it to interact with Java. * Perhaps most importantly, this class defines how you can share Java objects with * JRuby and how you can share JRuby objects back with Java interchangeably. * <br><br>This is especially nice if you have a need to not simply call JRuby * from Java or vice versa and would like to intermix the functionality in your * application. * @author Yoko Harada */ public class ReferringObjectsExample { private ReferringObjectsExample() throws ScriptException { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("jruby"); createObjectsInJava(engine); createObjectsInRuby(engine); } private void createObjectsInJava(ScriptEngine engine) throws ScriptException { // giving an object to Ruby as a global variable List list = new ArrayList(); list.add("What's up?"); list.add("How're you doing?"); list.add("How have you been?"); engine.put("list", list); String script = "$list.each {|msg| puts msg }"; engine.eval(script); engine.put("first", 2008); script = "$first.step(2015, 2) {|i| puts i }"; engine.eval(script); } // klauer: I'm not sure if this is exactly right. I had to change a couple things // - define the List as a List<String> in both seasons and colors instances // - define the Map as a Map<String, Float> for gpas. It works now, but // I'm not sure if I just abstracted something away, or if this was supposed // to compile without the need for generics. private void createObjectsInRuby(ScriptEngine engine) throws ScriptException { // referring an object as a global variable String script = "$seasons = ['spring', 'summer', 'fall', 'winter']"; engine.eval(script); List<String> seasons = (List) engine.get("seasons"); for (String season : seasons) { System.out.println(season); } // receiving an array object returned from Ruby script = "colors = ['red', 'green', 'white', 'blue'];"+ "colors.reverse"; List<String> colors = (List) engine.eval(script); for (String color : colors) { System.out.println(color); } // receiving a hash object returned from Ruby script = "gpas1 = {\"Alice\" => 3.75, \"Bob\" => 4.0};"+ "gpas2 = {\"Alice\" => 3.92, \"Chris\" => 3.55};"+ "gpas1.merge!(gpas2)"; Map<String, Float> gpas = (Map)engine.eval(script); for (String name : gpas.keySet()) { System.out.println(name +": " + gpas.get(name)); } } public static void main(String[] args) throws ScriptException { new ReferringObjectsExample(); } }