Created
December 12, 2010 04:58
-
-
Save qmx/737866 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<p><a href='/projects/jruby/pages/Home' class='internal'>» JRuby Project Wiki Home Page</a><h1>Embedding JRuby</h1> | |
Using Java from Ruby is JRuby's best-known feature---but you can also go in the other direction, and use Ruby from Java. There are several different ways to do this. You can execute entire Ruby scripts, call individual Ruby methods, or even implement a Java interface in Ruby (thus allowing you to treat Ruby objects like Java ones). We refer to all these techniques generically as "embedding." This section will explain how to embed JRuby in your Java project. | |
</p><div id='toc' class='toc'> | |
<div id='toctitle' class='toc-title'> | |
<span>Contents</span> | |
</div> | |
<div id='toccontents' class='toc-contents'><ul><li>1 <a href='#Red_Bridge_(JRuby_Embed)'> Red Bridge (JRuby Embed) </a></li> | |
<ul><li>1.1 <a href='#Features_of_Red_Bridge'> Features of Red Bridge </a></li> | |
<ul><li>1.1.1 <a href='#Context_Type'> Context Type </a></li> | |
<li>1.1.2 <a href='#Variables'> Variables </a></li> | |
</ul><li>1.2 <a href='#Download'> Download </a></li> | |
<ul><li>1.2.1 <a href='#Maven'> Maven </a></li> | |
</ul><li>1.3 <a href='#Getting_Started'> Getting Started </a></li> | |
<li>1.4 <a href='#Configurations'> Configurations </a></li> | |
<ul><li>1.4.1 <a href='#JRuby_Home'> JRuby Home </a></li> | |
<li>1.4.2 <a href='#Class_Path_(Load_Path)'> Class Path (Load Path) </a></li> | |
<li>1.4.3 <a href='#Context_Instance_Type'> Context Instance Type </a></li> | |
<ul><li>1.4.3.1 <a href='#Singleton'> Singleton </a></li> | |
<li>1.4.3.2 <a href='#ThreadSafe'> ThreadSafe </a></li> | |
<li>1.4.3.3 <a href='#SingleThread'> SingleThread </a></li> | |
</ul><li>1.4.4 <a href='#Local_Variable_Behavior_Options'> Local Variable Behavior Options </a></li> | |
<ul><li>1.4.4.1 <a href='#Transient_Local_Variable_Behavior'> Transient Local Variable Behavior </a></li> | |
<li>1.4.4.2 <a href='#Persistent_Local_Variable_Behavior'> Persistent Local Variable Behavior </a></li> | |
<li>1.4.4.3 <a href='#Global_Local_Variable_Behavior'> Global Local Variable Behavior </a></li> | |
<li>1.4.4.4 <a href='#BSF_Local_Variable_Behavior'> BSF Local Variable Behavior </a></li> | |
</ul><li>1.4.5 <a href='#CompileMode'> CompileMode </a></li> | |
<li>1.4.6 <a href='#Ruby_Version'> Ruby Version </a></li> | |
<li>1.4.7 <a href='#Line_Number'> Line Number </a></li> | |
<li>1.4.8 <a href='#Other_Ruby_Runtime_Configurations'> Other Ruby Runtime Configurations </a></li> | |
</ul><li>1.5 <a href='#Red_Bridge_Code_Examples'> Red Bridge Code Examples </a></li> | |
<li>1.6 <a href='#Red_Bridge_Servlet_Examples'> Red Bridge Servlet Examples </a></li> | |
<li>1.7 <a href='#Rewrite_it!'> Rewrite it! </a></li> | |
</ul><li>2 <a href='#See_Also'> See Also </a></li> | |
<li>3 <a href='#Previous_Embedding_JRuby_Page'> Previous Embedding JRuby Page</a></li> | |
</ul></div> | |
</div><p><br /> | |
</p><h1><a name='Red_Bridge_(JRuby_Embed)'></a> Red Bridge (JRuby Embed) </h1> | |
<p> | |
JRuby has long had a private embedding API, which was closely tied to the runtime's internals and therefore changed frequently as JRuby evolved. Since version 1.4, however, we have also provided a more stable public API, known as Red Bridge or JRuby Embed. Existing Java programs written to the <a href='/projects/jruby/pages/DirectJRubyEmbedding' class='internal'>legacy API</a> should still work, but we strongly recommend Red Bridge for all new projects. | |
</p><h2><a name='Features_of_Red_Bridge'></a> Features of Red Bridge </h2> | |
<p>Red Bridge consists of two layers: Embed Core on the bottom, and implementations of <a class='external' href="http://www.jcp.org/en/jsr/detail?id=223">JSR223</a> and <a class='external' href="http://jakarta.apache.org/bsf/">BSF</a> on top. Embed Core is JRuby-specific, and can take advantage of much of JRuby's power. JSR223 and BSF are more general interfaces that provide a common ground across scripting languages. | |
</p><p>Which API should you use? For projects where Ruby is the only scripting language involved, we recommend Embed Core for the following reasons: | |
</p><ol><li> With Embed Core, you can create several Ruby environments in one JVM, and configure them individually (via <code>org.jruby.RubyInstanceConfig</code>. With the other APIs, configuration options can only be set globally, via the <code>System</code> properties. | |
</li><li> Embed Core offers several shortcuts, such as loading scripts from a <code>java.io.InputStream</code>, or returning Java-friendly objects from Ruby code. These allow you to skip a lot of boilerplate. | |
</li></ol><p> | |
For projects requiring multiple scripting languages, JSR223 is a good fit. Though the API is language-independent, JRuby's implementation of it allows you to set some Ruby-specific options. In particular, you can control the threading model of the scripting engine, the lifetime of local variables, compilation mode, and how line numbers are displayed. | |
</p><p>The full <a class='external' href="http://jruby-embed.kenai.com/docs/">API documentation</a> has all the gory details. It's worth talking about a couple of the finer points here. | |
</p><h3><a name='Context_Type'></a> Context Type </h3> | |
<p> | |
The context type (singleton, thread-safe, or single-threaded) determines how JRuby maintains its internal Ruby state. Choosing the wrong type can lead to surprising results, so it's worth talking about how to choose the right one. | |
</p><p>For simple cases where you're only using one Ruby runtime across your Java program, and you don't need to access it from multiple threads, choose the singleton type. If you want to run Ruby scripts in a multi-threaded environment, you should use the thread-safe type instead. | |
</p><h3><a name='Variables'></a> Variables </h3> | |
<p> | |
Variable sharing is one area where RedBridge provides additional power to you. Typical scripting APIs rely on the blunt instrument of global variables to share data. With this approach, you'd set a few globals (remembering to use <code>$</code> at the beginning of the variable name for Ruby), run a script, and then retrieve the results through other globals. | |
</p><p>RedBridge allows this use, of course, but offers better choices as well. You can easily share not just global variables, but also local and instance variables, across the Ruby / Java divide. JRuby uses a mechanism called a <i>variable map</i> to track variable names and values between Ruby and Java. Various options control how this variable map is reused from one invocation to another. | |
</p><p>You can also pass data in through method arguments, and work directly with return values. These values are accessible on the Java side as normal Java objects: you're not forced to convert everything to strings or primitive types. | |
</p><h2><a name='Download'></a> Download </h2> | |
<p> | |
JRuby Embed (Red Bridge) binaries have been included in the official <a class='external' href="http://www.jruby.org/download">JRuby download</a> since 1.4.0RC1. Starting with version 1.5, the Red Bridge <i>source</i> will be included in JRuby source archives as well. Until then, the source will be available separately from the JRuby Embed <a class='external' href="http://kenai.com/projects/jruby-embed/sources">repository</a> and <a class='external' href="http://kenai.com/projects/jruby-embed/downloads">archives</a>. | |
</p><p>JSR 223 and BSF are stable APIs. The Embed Core API is somewhat stable, but may change slightly from release to release. | |
</p><h3><a name='Maven'></a> Maven </h3> | |
<p> | |
The JRuby 1.4.0x archives in maven repo don't include JRuby Embed. The codehaus repo does, though, so please add the following to your <code>pom.xml</code> if you need embedding support: | |
<pre name="code" class="xml"> | |
..... | |
<repository> | |
<id>codehaus</id> | |
<name>Maven Codehaus repository</name> | |
<url>http://repository.codehaus.org/</url> | |
</repository> | |
.... | |
.... | |
<dependency> | |
<groupId>org.jruby.embed</groupId> | |
<artifactId>jruby-embed</artifactId> | |
<version>0.1.2</version> | |
</dependency> | |
.... | |
</pre> | |
</p><p>This extra step will be unnecessary starting with JRuby 1.5. | |
</p><h2><a name='Getting_Started'></a> Getting Started </h2> | |
<p> | |
A simple 'Hello World' example is a great way to get to know Red Bridge. | |
</p><p>Before you start programming, make sure the necessary jar archives are in your classpath: | |
</p><dl><dt>- Core | |
</dt></dl><ul><li> <code>jruby-complete.jar</code> or <code>jruby.jar</code></li></ul><dl><dt>- JSR223 | |
</dt></dl><ul><li> <code>jruby-complete.jar</code> or <code>jruby.jar</code></li><li> <code>script-api.jar</code> (if you are using JDK1.5) | |
</li></ul><dl><dt>- BSF | |
</dt></dl><ul><li> <code>jruby-complete.jar</code> or <code>jruby.jar</code></li><li> <code>bsf.jar</code></li><li> <code>commons-logging-[version].jar</code></li></ul><p> | |
Here's how to execute a simple Ruby script (<code>puts "Hello World!"</code>) using the three JRuby Embed APIs: | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
package vanilla; | |
import org.jruby.embed.ScriptingContainer; | |
public class HelloWorld { | |
private HelloWorld() { | |
ScriptingContainer container = new ScriptingContainer(); | |
container.runScriptlet("puts \"Hello World!\""); | |
} | |
public static void main(String[] args) { | |
new HelloWorld(); | |
} | |
}</pre> | |
</p><ul><li> JSR223 | |
</li></ul><p><pre name="code" class="java"> | |
package redbridge; | |
import javax.script.ScriptEngine; | |
import javax.script.ScriptEngineManager; | |
import javax.script.ScriptException; | |
public class Jsr223HelloWorld { | |
private Jsr223HelloWorld() throws ScriptException { | |
ScriptEngineManager manager = new ScriptEngineManager(); | |
ScriptEngine engine = manager.getEngineByName("jruby"); | |
engine.eval("puts \"Hello World!\""); | |
} | |
public static void main(String[] args) throws ScriptException { | |
new Jsr223HelloWorld(); | |
} | |
}</pre> | |
</p><ul><li> BSF | |
</li></ul><p><pre name="code" class="java"> | |
package azuki; | |
import org.apache.bsf.BSFException; | |
import org.apache.bsf.BSFManager; | |
public class BsfHelloWorld { | |
private BsfHelloWorld() throws BSFException { | |
BSFManager.registerScriptingEngine("jruby", "org.jruby.embed.bsf.JRubyEngine", new String[] {"rb"}); | |
BSFManager manager = new BSFManager(); | |
manager.exec("jruby", "<script>", 0, 0, "puts \"Hello World!\""); | |
} | |
public static void main(String[] args) throws BSFException { | |
new BsfHelloWorld(); | |
} | |
}</pre> | |
</p><p>All three programs print out "Hello World!" to standard output. | |
</p><h2><a name='Configurations'></a> Configurations </h2> | |
<p> | |
JRuby Embed allows you to configure its environment and behavior. In many cases, the default options are all you need. For situations when you want more control, you can use the options described in this section. | |
</p><p>With Embed Core, you typically set options through constructor or method arguments. With JSR223, you use <code>System</code> properties instead. | |
</p><p>RedBridge supports both per-container ("per-engine," in JSR223 parlance) and per-evaluation options. When you set per-container options using system properties, you must set before instantiating a scripting container or engine. When you set options using methods of Embed Core, you must set before using put/parse/runScriptlet methods. These methods instantiate and initialize Ruby runtime based on the configuration. Once Ruby runtime has been initialized, per-container configuration won't be referred anymore. Per-evaluation options should be set just before running Ruby code. | |
</p><ul><li>Per-container configurations: | |
<ul><li>JRuby Home | |
</li><li>Classpath | |
</li><li>Context Instance Type | |
</li><li>Local Variable Behavior | |
</li><li>Compile Mode | |
</li><li>Ruby Version | |
</li></ul></li></ul><ul><li>Per-evaluation configurations: | |
<ul><li> Line Number | |
</li></ul></li></ul><p> | |
As of JRuby 1.5.0, Red Bridge offers several configuration methods. This helps separate the internal API from the publicly used one. Please see <a href='/projects/jruby/pages/JRubyOptions' class='internal'>JRubyOptions</a> for a list of JRuby options supported by Red Bridge. | |
</p><h3><a name='JRuby_Home'></a> JRuby Home </h3> | |
<p> | |
Scope: Per Container<br /> | |
Propety Name: jruby.home | |
</p><p>JRuby Home is is where JRuby looks for its built-in libraries. Internally, JRuby Embed first checks for the <code>JRUBY_HOME</code> environment variable, then the <code>jruby.home</code> system property, then the value embedded in <code>jruby-complete.jar</code>. Using <code>jruby-complete.jar</code> is the simplest approach, because it frees you from having to set this option yourself. | |
</p><p>If you'd rather use the environment variable, you can set it from your OS . Here's what that looks like on UNIX and OS X (assuming your shell is <code>bash</code>): | |
</p><p><pre> | |
export JRUBY_HOME=/Users/yoko/Tools/jruby-1.3.1</pre> | |
</p><p>The other alternative is the <code>jruby.home system</code> property. There are two ways to set its value: via the command line, or using <code>java.langSystem#setProperty()</code>. | |
</p><ul><li> Core, JSR223, BSF | |
</li></ul><p><pre> | |
java âJ-Djruby.home=/Users/yoko/Tools/jruby-1.3.1 âcp â¦</pre><pre name="code" class="java"> | |
System.setProperty("jruby.home", "/Users/yoko/Tools/jruby-1.3.1"); | |
ScriptingContainer container = new ScriptingContainer();</pre> | |
</p><p>With Embed Core, you can also set <code>jruby.home</code> individually for each scripting container instance: | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
ScriptingContainer container = new ScriptingContainer(); | |
container.getProvider().getRubyInstanceConfig().setJRubyHome("/Users/yoko/Tools/jruby-1.3.1");</pre> | |
</p><h3><a name='Class_Path_(Load_Path)'></a> Class Path (Load Path) </h3> | |
<p> | |
Scope: Per Container<br /> | |
Propety Name: org.jruby.embed.class.path (or java.class.path) | |
</p><p>Classpaths are used to load Ruby scripts as well as Java classes and jar archives. Embed Core and BSF have a method to set classpath. However, JSR223 doesn't have such method or method argument. Thus, JSR223 need to be set classpath by system property. Either org.jruby.embed.class.path or java.class.path property names can be used to set classpath. The org.jruby.embed.class.path system property is avaiable to use in Embed Core and BSF, too. In case of Embed Core and JSR223, a value assigned to org.jruby.embed.class.path is looked up first, then java.class.path. This means that only org.jruby.embed.class.path is used if exists. As for BSF, after java.class.path is looked up, org.jruby.embed.class.path is added to if exists. The format of the paths is the same as Java's class path syntax, :(colon) separated path string on Unix and OS X or ;(semi-colon) separated one on Windows. Be sure to set classpaths before you instantiate javax.script.ScriptEngineManager or register engine to org.apache.bsf.BSFManager. A related topic is in <a href='/projects/jruby/pages/ClasspathAndLoadPath' class='internal'>ClasspathAndLoadPath</a> | |
</p><p>Samples below run testMath.rb, which is included in JRubyâs source archive. The script, testMath.rb, needs minirunit.rb, which should be loaded from the classpath. | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
package vanilla; | |
import java.util.ArrayList; | |
import java.util.List; | |
import org.jruby.embed.PathType; | |
import org.jruby.embed.ScriptingContainer; | |
public class LoadPathSample { | |
private final static String jrubyhome = "/Users/yoko/Tools/jruby-1.3.1"; | |
private final String filename = jrubyhome + "/test/testMath.rb"; | |
private LoadPathSample() { | |
ScriptingContainer container = new ScriptingContainer(); | |
List<String> loadPaths = new ArrayList(); | |
loadPaths.add(jrubyhome); | |
container.getProvider().setLoadPaths(loadPaths); | |
container.runScriptlet(PathType.ABSOLUTE, filename); | |
} | |
public static void main(String[] args) { | |
new LoadPathSample(); | |
} | |
}</pre> | |
</p><ul><li> JSR223 | |
</li></ul><p><pre name="code" class="java"> | |
package redbridge; | |
import java.io.FileNotFoundException; | |
import java.io.FileReader; | |
import java.io.Reader; | |
import javax.script.ScriptEngine; | |
import javax.script.ScriptEngineManager; | |
import javax.script.ScriptException; | |
public class Jsr223LoadPathSample { | |
private final static String jrubyhome = "/Users/yoko/Tools/jruby-1.3.1"; | |
private final String filename = jrubyhome + "/test/testMath.rb"; | |
private Jsr223LoadPathSample() throws ScriptException, FileNotFoundException { | |
System.setProperty("org.jruby.embed.class.path", jrubyhome); | |
ScriptEngineManager manager = new ScriptEngineManager(); | |
ScriptEngine engine = manager.getEngineByName("jruby"); | |
Reader reader = new FileReader(filename); | |
engine.eval(reader); | |
} | |
public static void main(String[] args) throws ScriptException, FileNotFoundException { | |
new Jsr223LoadPathSample(); | |
} | |
} </pre> | |
</p><ul><li> BSF | |
</li></ul><p><pre name="code" class="java"> | |
package azuki; | |
import java.io.FileNotFoundException; | |
import org.apache.bsf.BSFException; | |
import org.apache.bsf.BSFManager; | |
import org.jruby.embed.PathType; | |
public class BsfLoadPathSample { | |
private final static String jrubyhome = "/Users/yoko/Tools/jruby-1.3.1"; | |
private final String filename = jrubyhome + "/test/testMath.rb"; | |
private BsfLoadPathSample() throws BSFException, FileNotFoundException { | |
BSFManager.registerScriptingEngine("jruby", "org.jruby.embed.bsf.JRubyEngine", new String[] {"rb"}); | |
BSFManager manager = new BSFManager(); | |
manager.setClassPath(jrubyhome); | |
manager.exec("jruby", filename, 0, 0, PathType.ABSOLUTE); | |
} | |
public static void main(String[] args) throws BSFException, FileNotFoundException { | |
new BsfLoadPathSample(); | |
} | |
}</pre> | |
</p><p><br /> | |
</p><h3><a name='Context_Instance_Type'></a> Context Instance Type </h3> | |
<p> | |
Scope: Per Container<br /> | |
Property Name: org.jruby.embed.localcontext.scope<br /> | |
Value: <b>singleton</b>(default in JRuby 1.4.0 and JRuby trunk; rev. 9e557a2 and later, JRuby Embed 0.1.3),<br /><b>theadsafe</b> (default in JRuby 1.4.0RC1, RC2, RC3, and JRuby Embed 0.1.2),<br /> | |
or <b>singlethread</b> | |
</p><p>The context instance type is a type of a local context. The local context holds Ruby runtime, name-value pairs for sharing variables between Java and Ruby, default I/O streams (reader/writer/error writer), and attributes. The context is saved in one of three types, threadsafe, singlethread, or singleton. Three types are defined in org.jruby.embed.LocalContextScope and also can be set by a system property. | |
</p><p>Make sure to set the context type before you instantiate javax.script.ScriptEngineManager or register engine to org.apache.bsf.BSFManager. | |
</p><h4><a name='Singleton'></a> Singleton </h4> | |
<p>This model uses a well known Singleton pattern, and the only one instance of a local context will exist on JVM.<br /> | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
ScriptingContainer instance = new ScriptingContainer(LocalContextScope.SINGLETON); | |
</pre> | |
</p><ul><li> JSR223/BSF | |
</li></ul><p><pre name="code" class="java"> | |
System.setProperty("org.jruby.embed.localcontext.scope", "singleton"); | |
</pre> | |
</p><p><br /> | |
</p><h4><a name='ThreadSafe'></a> ThreadSafe </h4> | |
<p>Script's parsings and evaluations should be safely performed on a multi-threaded environment such as servlet container. A supposed usage is that ScriptEngine is instantiateted in servlet's init() method and evaluates scripts in servlet's service() method.<br /> | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
ScriptingContainer instance = new ScriptingContainer(LocalContextScope.THREADSAFE); | |
</pre> | |
</p><ul><li> JSR223/BSF | |
</li></ul><p><pre name="code" class="java"> | |
System.setProperty("org.jruby.embed.localcontext.scope", "threadsafe"); | |
</pre> | |
</p><h4><a name='SingleThread'></a> SingleThread </h4> | |
<p>This model pretends as if there is only one thread in the world, and does not mind race condition at all. Users are resposnsible to thread safety. If you want to instantiate ScriptEngine in servlet's service() method, this model would be the best suited one. | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
ScriptingContainer instance = new ScriptingContainer(LocalContextScope.SINGLETHREAD); | |
</pre> | |
</p><ul><li> JSR223/BSF | |
</li></ul><p><pre name="code" class="java"> | |
System.setProperty("org.jruby.embed.localcontext.scope", "singlethread"); | |
</pre> | |
</p><p><br /> | |
</p><h3><a name='Local_Variable_Behavior_Options'></a> Local Variable Behavior Options </h3> | |
<p> | |
Scope: Per Container<br /> | |
Property Name: org.jruby.embed.localvariable.behavior<br /> | |
Value: <b>transient</b> (default for core), <b>persistent</b>, <b>global</b> (default for JSR223), or <b>bsf</b> (for BSF) | |
</p><p>JRuby Embed enables to share Ruby's local, instance, global variables, and constants. To share these variables between Ruby and Java, JRuby Embed offers four types of local variable behaviors, transient, persistent, global, and bsf. Four types are defined in org.jruby.embed.LocalVariableBehavior and also can be set by a system property. | |
</p><h4><a name='Transient_Local_Variable_Behavior'></a> Transient Local Variable Behavior </h4> | |
<p> | |
Default for Embed Core. Local variables' scope is faithful to Ruby semantics. This means local variable does not survive over the multiple evaluations. After the each evaluation, local variable will vanish away. However, instance and global variables, and constants survive unless those are removed explicitly. If you use global variables, the variables can be referred literally globally in Ruby runtime and exist as long as the runtime is alive. Be careful to the scope of global variables so that you donât mix in vulnerabilities in a web application.<br /> | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
ScriptingContainer instance = new ScriptingContainer(); | |
</pre> | |
or | |
<pre name="code" class="java"> | |
ScriptingContainer instance = new ScriptingContainer(LocalVariableBehavior.TRANSIENT); | |
</pre> | |
or | |
<pre name="code" class="java"> | |
ScriptingContainer instance = new ScriptingContainer(LocalContextScope.SINGLETHREAD, LocalVariableBehavior.TRANSIENT); | |
</pre> | |
</p><ul><li> JSR223 | |
</li></ul><p><pre name="code" class="java"> | |
System.setProperty("org.jruby.embed.localvariable.behavior", "transient"); | |
ScriptEngineManager manager = new ScriptEngineManager(); | |
ScriptEngine engine = manager.getEngineByName("jruby"); | |
</pre> | |
</p><ul><li> BSF | |
</li></ul><p>BSF can choose only BSF type. | |
</p><h4><a name='Persistent_Local_Variable_Behavior'></a> Persistent Local Variable Behavior </h4> | |
<p> | |
When this type is chosen, JRuby Embed keeps sharing all local variables' over multiple evaluations. This might not be a semantically correct usage, but is useful in some cases especially for users who have BSF background.<br /> | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
ScriptingContainer instance = new ScriptingContainer(LocalVariableBehavior.PERSISTENT); | |
</pre> | |
or | |
<pre name="code" class="java"> | |
ScriptingContainer instance = new ScriptingContainer(LocalContextScope.SINGLETHREAD, LocalVariableBehavior.PERSISTENT); | |
</pre> | |
</p><ul><li> JSR223 | |
</li></ul><p><pre name="code" class="java"> | |
System.setProperty("org.jruby.embed.localvariable.behavior", "persistent"); | |
ScriptEngineManager manager = new ScriptEngineManager(); | |
ScriptEngine engine = manager.getEngineByName("jruby"); | |
</pre> | |
</p><ul><li> BSF | |
</li></ul><p>BSF can choose only BSF type. | |
</p><h4><a name='Global_Local_Variable_Behavior'></a> Global Local Variable Behavior </h4> | |
<p> | |
Default for JSR223. This behavior might be convenient to users who have used JSR223 reference implementation released at scripging.dev.java.net and don't want change any code at all. With names like Ruby's local variable name, variables are mapped to Ruby's global variables. Only global variables can be shared between Ruby and Java, when this behavior is chosen. The values of global variables of this type are not kept over the evaluations. <br /> | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
ScriptingContainer instance = new ScriptingContainer(LocalVariableBehavior.GLOBAL); | |
</pre> | |
</p><ul><li> JSR223 | |
</li></ul><p><pre name="code" class="java"> | |
System.setProperty("org.jruby.embed.localvariable.behavior", "global"); | |
ScriptEngineManager manager = new ScriptEngineManager(); | |
ScriptEngine engine = manager.getEngineByName("jruby"); | |
</pre> | |
</p><ul><li> BSF | |
</li></ul><p>BSF can choose only BSF type. | |
</p><h4><a name='BSF_Local_Variable_Behavior'></a> BSF Local Variable Behavior </h4> | |
<p> | |
Default for BSF. Local and global variables are available to share between Java and Ruby. Variable names doesnât start with â$â no matter what the variable types are. Since BSF has a method defined for sharing local variables, it doesnât confuse. However, core and JSR223 will confuse variables, so donât use this type for them.<br /> | |
</p><ul><li> Core/JSR223 | |
</li></ul><p>Donât choose this behavior. | |
</p><ul><li>BSF | |
</li></ul><p><pre name="code" class="java"> | |
BSFManager.registerScriptingEngine("jruby", "org.jruby.embed.bsf.JRubyEngine", new String[] {"rb"}); | |
BSFManager manager = new BSFManager(); | |
</pre> | |
or | |
<pre name="code" class="java"> | |
System.setProperty("org.jruby.embed.localvariable.behavior", "bsf"); | |
BSFManager.registerScriptingEngine("jruby", "org.jruby.embed.bsf.JRubyEngine", new String[] {"rb"}); | |
BSFManager manager = new BSFManager(); | |
</pre> | |
</p><h3><a name='CompileMode'></a> CompileMode </h3> | |
<p> | |
Scope: Per Container<br /> | |
Property Name: org.jruby.embed.compilemode<br /> | |
Value: off (default), jit, or force | |
</p><p>JRuby has jit and force options to compile Ruby scripts. This configuration provides users a way of setting a compile mode. When jit or force is specified, only a global variable can be shared between Ruby and Java. | |
</p><p>This option is not for pre-compiled Ruby scripts. Ruby2java <a class='external' href="http://kenai.com/projects/ruby2java">http://kenai.com/projects/ruby2java</a> generated Java classes are not executable on current JRuby Embed. | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
ScriptingContainer container = new ScriptingContainer(); | |
container.getProvider().getRubyInstanceConfig().setCompileMode(CompileMode.JIT); | |
</pre> | |
</p><ul><li>JSR223/BSF | |
</li></ul><p><pre name="code" class="java"> | |
System.setProperty("org.jruby.embed.compilemode", "jit"); | |
</pre> | |
</p><h3><a name='Ruby_Version'></a> Ruby Version </h3> | |
<p> | |
Scope: Per Container<br /> | |
Property Name: org.jruby.embed.compat.version<br /> | |
Value: jruby19, JRuby1_9, ruby1.9â¦.matches [jJ]?(r|R)(u|U)(b|B)(y|Y)1[\\._]?9 | |
</p><p>Default Ruby version is 1.8. When you want to use Ruby 1.9 on JRuby Embed, you need to specify the version. In case of Embed Core, the method to set the version is available to use. JSR223 needs system property to recognize the version. BSF judges the registered name. If the system property name or registered name matches the regular expression, [jJ]?(r|R)(u|U)(b|B)(y|Y)1[\\._]?9, Ruby 1.9 is chosen to run scripts. If no system property is there, or matching fails, Ruby 1.8 is chosen. | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
ScriptingContainer container = new ScriptingContainer(); container.getProvider().getRubyInstanceConfig().setCompatVersion(CompatVersion.RUBY1_9); | |
</pre> | |
</p><ul><li> JSR223 | |
</li></ul><p><pre name="code" class="java"> | |
System.setProperty("org.jruby.embed.compat.version", "JRuby1.9"); | |
JRubyScriptEngineManager manager = new JRubyScriptEngineManager(); | |
JRubyEngine engine = (JRubyEngine) manager.getEngineByName("jruby"); | |
</pre> | |
</p><ul><li>BSF | |
</li></ul><p><pre name="code" class="java"> | |
BSFManager.registerScriptingEngine("jruby19", "org.jruby.embed.bsf.JRubyEngine", new String[] {"rb"}); | |
BSFManager manager = new BSFManager(); | |
manager.exec("jruby19", "ruby/block-param-scope.rb", 0, 0, PathType.CLASSPATH); | |
</pre> | |
</p><h3><a name='Line_Number'></a> Line Number </h3> | |
<p> | |
Scope: Per Evaluation<br /> | |
Attribute Name: org.jruby.embed.linenumber<br /> | |
Value: 1, 2, 3,,,, (integer) | |
</p><p>Embed Core and BSF have a method argument to set a line number to display for parse errors and backtracks, but JSR223 doesnât. When you want to specify a line number on JSR223, use the attribute. | |
</p><ul><li> Core | |
</li></ul><p><pre name="code" class="java"> | |
private final String script = | |
"puts \"Hello World.\"\n" + | |
"puts \"Error is here."; | |
ScriptingContainer container = new ScriptingContainer(); | |
EvalUnit unit = container.parse(script, 1); | |
Object ret = unit.run();</pre> | |
</p><ul><li> JSR223 | |
</li></ul><p><pre name="code" class="java"> | |
import javax.script.ScriptContext; | |
import javax.script.ScriptEngine; | |
import javax.script.ScriptException; | |
import org.jruby.embed.jsr223.JRubyScriptEngineManager; | |
public class LineNumberSample { | |
private final String script = | |
"puts \"Hello World.\"\n" + | |
"puts \"Error is here."; | |
private LineNumberSample() throws ScriptException { | |
JRubyScriptEngineManager manager = new JRubyScriptEngineManager(); | |
ScriptEngine engine = manager.getEngineByName("jruby"); | |
try { | |
engine.eval(script); // Since no line number is given, 0 is applied to. | |
} catch (Exception e) { | |
; | |
} | |
try { | |
engine.getContext().setAttribute("org.jruby.embed.linenumber", 1, ScriptContext.ENGINE_SCOPE); | |
engine.eval(script); | |
} catch (Exception e) { | |
; | |
} | |
try { | |
engine.getContext().setAttribute("org.jruby.embed.linenumber", 2, ScriptContext.ENGINE_SCOPE); | |
engine.eval(script); | |
} catch (Exception e) { | |
; | |
} | |
} | |
public static void main(String[] args) | |
throws ScriptException { | |
new LineNumberSample(); | |
} | |
}</pre> | |
</p><p>Outputs:<pre> | |
:1: <script>:2: unterminated string meets end of file (SyntaxError) | |
:1: <script>:3: unterminated string meets end of file (SyntaxError) | |
:1: <script>:4: unterminated string meets end of file (SyntaxError) | |
</pre> | |
</p><ul><li> BSF | |
</li></ul><p><pre name="code" class="java"> | |
private final String script = | |
"puts \"Hello World.\"\n" + | |
"puts \"Error is here."; | |
BSFManager.registerScriptingEngine("jruby", "org.jruby.embed.bsf.JRubyEngine", new String[] {"rb"}); | |
BSFManager manager = new BSFManager(); | |
manager.exec("jruby", â<script>â, 1, 0, script);</pre> | |
</p><h3><a name='Other_Ruby_Runtime_Configurations'></a> Other Ruby Runtime Configurations </h3> | |
<p> | |
If you need more fine-grained control over the Ruby runtime than what's shown here, you can use the various methods of <code>org.jruby.RubyInstanceConfig</code> in Embed Core. Here's the recommended sequence: | |
</p><p><pre name="code" class="java"> | |
ScriptingContainer container = new ScriptingContainer(); | |
RubyInstanceConfig config = container.getProvider().getRubyInstanceConfig(); | |
# First, make the configuration changes you need. | |
config.someConfigMethod(...); | |
# Now, you can set variables or run Ruby code. | |
container.runScriptlet(...);</pre> | |
</p><p>JSR223 and BSF don't support as many configuration options as Embed Core. If you need additional options in these APIs, please file a request in the <a class='external' href="http://jra.codehau.org/browe/JRUBY">issue tracker</a>. | |
</p><h2><a name='Red_Bridge_Code_Examples'></a> Red Bridge Code Examples </h2> | |
<p>See the <a href='/projects/jruby/pages/RedBridgeExamples' class='internal'>RedBridgeExamples</a> page. | |
</p><h2><a name='Red_Bridge_Servlet_Examples'></a> Red Bridge Servlet Examples </h2> | |
<p>See the <a href='/projects/jruby/pages/RedBridgeServletExamples' class='internal'>RedBridgeServletExamples</a> page. | |
</p><h2><a name='Rewrite_it!'></a> Rewrite it! </h2> | |
<p>See the <a href='/projects/jruby/pages/RedBridgeWay' class='internal'>RedBridgeWay</a> page. | |
</p><h1><a name='See_Also'></a> See Also </h1> | |
<ul><li> <a href='/projects/jruby/pages/JRubyOptions' class='internal'>JRubyOptions</a></li><li> <a href='/projects/jruby/pages/CallingJavaFromJRuby' class='internal'>Calling Java from JRuby</a></li><li> <a href='/projects/jruby/pages/AccessingJRubyObjectInJava' class='internal'>Accessing JRuby Object in Java</a></li><li> <a class='external' href="http://www.blogger.com/posts.g?blogID=22066395&searchType=ALL&txtKeywords=&label=RedBridge">JRuby Embed (Red Bridge) info</a></li><li> <a class='external' href="http://jruby-embed.kenai.com/docs/">JRuby Embed API document</a></li></ul><h1><a name='Previous_Embedding_JRuby_Page'></a> Previous Embedding JRuby Page</h1> | |
<p>We recommend using Embed Core; however, if you're maintaining code that uses the old API, you can find its documentation on the <a href='/projects/jruby/pages/JavaIntegration' class='internal'>legacy embedding</a> page. | |
</p> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment