CSC/ECE 517 Fall 2012/ch1 1w6 pp: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 185: Line 185:
== Further Reading ==
== Further Reading ==


Using JRuby Bringing Ruby to Java by Charles O Nutter, Nick Sieger, Thomas Enebo, Ola Bini, and Ian Dees
Using JRuby Bringing Ruby to Java by Charles O Nutter

Revision as of 18:53, 9 September 2012

This page is about the mixing static and dynamic Object Oriented code. This page will mention some difficulties when these two types of object orientation are mixed and then we will give on practical example of such in JRuby. JRuby is mixing of Java and Ruby, this page will cover the different types of such mixings and examples of each of them.


Introduction

Difficulties in mixing static and dynamic oo

If the static oo makes use of generics for e.g. Java, then the generic types are erased during compilation for backward compatibility. As a result for a dynamically types language like Ruby, there will be problems with type conversion. For example, if you have a Map<String,String>, it will be seen as a simple Map, and JRuby will not be able to determine the correct types using reflection.

JRuby

The Ruby Programming Language on the JVM. Ruby is a reflective, dynamic, and interpreted object-oriented scripting language. JRuby is a Java programming language implementation of the Ruby language syntax, core libraries, and standard libraries. With JRuby, you get all of the advantages of Ruby plus access to the full range of Java platform functionality.

Some examples where this integration can be done are:

1) From a JRuby script, you can call the Java platform Math library to access its powerful computational capabilities or call the Java platform Swing library to display a dialog box that requires end-user input before allowing the script to proceed.
2) You can use the JSR 223 Scripting APIs or the Bean Scripting Framework (BSF) APIs to call a JRuby script from within a Java application to, for example, invoke back-end processing scripts from a servlet to update or generate web content.

Advantages of JRuby

Advantages of JRuby over Ruby

  • With JRuby you get the best of both worlds: Ruby applications and libraries, plus Java libraries. Anthreads, JRuby supports Unicode natively
  • Code can be fully compiled ahead of time or just in time.
  • In addition to native you can access those libraries with Ruby syntax (or Java syntax, if you want).
  • On average JRuby, runs 2 and a half times faster than Ruby, except at startup

Advantages of JRuby over Java

  • Ruby is fun, beautiful, and powerful language
  • Ruby has features which are missing from Java

Closure (blocks)
Open classes
Meta programming
Duck-typing
Domain Specific Language (DSL)

Examples JRuby

Driving Java from Ruby

This involves calling Java methods from Ruby. This includes adding some java functionality in the Ruby code. The final code will be run on JVM. Ruby code can load and interact with Java Libraries. As a simple example we can use an ArrayList from java into Ruby code as below:

require ‘java’

list = java.util.ArrayList.new

list << ‘List of’
list << 3 
list << :assorted_items

list.each do |item|
puts “#{item.class}: #{item}”
end

Instead of just requiring a specific class you can also require the entire package. This can be done as follows:

module JavaLangDemo
  include_package "java.lang"
  # alternately, use the #import method
  import "java.lang"
end

One has to be careful in doing this as with name conflicts in both Ruby and Java can lead to losing the Ruby functionality. For example if a File object is created using Java’s java.io.File class, then the Ruby constant File becomes useless -

import java.io.File
newfile = File.new("file.txt")

and then using -

File.open('README', 'r') {|f| puts f.readline }

This will give the error - NoMethodError: private method `open' called for Java::JavaIo::File:Class

This situation can be avoided by including the package in the module definition and then using that module scope to create using that File object.

newfile = JavaIO::File.new("file.txt")

JRuby will forward any option to the underlying Java runtime if you preface it with -J.

Ruby from Java

There are three ways for using the JRuby Interpreter from Java namely, Embedding JRuby, using JSR 223 and the Bean Scripting Framework.

Embedding JRuby

Embed Core is the main embedding API that ships with JRuby. This API offers a great deal of interoperability. You can call a Ruby method, crunch the results in Java, and hand data back into Ruby.

JSR 223, Scripting for the Java Platform

This provides an API framework for calling scripting code from within a Java application and passing data between the application and the script. These features make it possible to combine existing scripts with Java applications and to extend a Java application with general-purpose scripts that other Java applications can also use. JSR 223 Scripting APIs are available in JDK 6 software, and by default, the APIs support the JavaScript programming language. With a little setup as described in the section JRuby Scripting Engine Setup, you can use the JSR 223 Scripting APIs with any JSR 223-compliant scripting engine such as JRuby.

Steps: Java integration with Java 6 will be using the standard scripting API (JSR223). A JRuby scripting engine already exists and is located at https://scripting.dev.java.net/. Download and unzip the collection of jars from the documents and files section of the site (jsr223-engines.tar.gz or jsr223-engines.zip). Look in the uncompressed files for the jruby/build/jruby-engine.jar file. Add this file to your classpath and then use the code below to access the engine.

import javax.script.*;

public class jrubytry {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager factory = new ScriptEngineManager();

        // Create a JRuby engine.
        ScriptEngine engine = factory.getEngineByName("jruby");

        // Evaluate JRuby code from string.
        try {
            engine.eval("puts('Hello')");
        } catch (ScriptException exception) {
            exception.printStackTrace();
        }
    }
}

The Bean Scripting Framework (BSF)

This is another way to call scripting code from within a Java application.

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 theBSF.jar file into your JAVA_HOME/lib/ext/ folder. Then, try the following:

import org.jruby.Ruby.*;
import org.jruby.*;
import org.jruby.javasupport.bsf.*;
import org.apache.bsf.BSFException;
import org.apache.bsf.BSFManager;
{...}
JLabel mylabel = new JLabel();
BSFManager.registerScriptingEngine("ruby", 
                                   "org.jruby.javasupport.bsf.JRubyEngine", 
                                   new String[] { "rb" });

BSFManager manager = new BSFManager();

/* Import an object using declareBean then you can access it in JRuby with $<name> */
 
manager.declareBean("label", mylabel, JFrame.class);
manager.exec("ruby", "(java)", 1, 1, "$label.setText(\"This is a test.\")");


Difficulties with JRuby

Larger memory footprint and startup time

A single JRuby instance needs more memory than a single Ruby instance, but in a typical production server environment with multiple mongrels, memory can be shared so that I expect a lower or at least equal memory usage in total. JRuby’s startup time is higher than MRI, but once the JVM has “warmed up” after a few minutes, it usually runs faster than MRI.

No native C extension

Due to the nature of Java, it is impossible to run any native extension. So there are several gems that don’t work since they rely on a C extension. However, there’s ongoing effort to create alternative gems that are compatible to JRuby. E.g. mongrel uses a native C extension, but if you install the mongrel gem using JRuby, it automatically installs a java-enhanced version.

JRuby is not technically complete

It’s told that there are cases where JRuby is not 100% compatible with MRI, however, I think these are very special cases; at least I didn’t encounter any problems yet. Big Frameworks like Rails are tested with JRuby, so I currently don’t expect any problems with it.

References

http://www.javaworld.com/javaworld/jw-07-2006/jw-0717-ruby.html
http://java.sun.com/developer/technicalArticles/scripting/jruby/
http://en.wikipedia.org/wiki/JRuby
http://nealford.com/downloads/conferences/JRuby_Tutorial%28Neal_Ford%29.pdf
http://rubysource.com/learning-more-about-jruby-from-charles-nutter/
https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
http://media.pragprog.com/titles/jruby/embed.pdf
https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
http://www.coderanch.com/t/461625/Ruby/JRuby-benefits
http://zargony.com/2008/09/26/why-i-m-starting-to-like-jruby-even-though-i-dislike-java
https://github.com/jruby/jruby/wiki/JavaIntegration#wiki-Java_6_using_JSR_223_Scripting
https://github.com/jruby/jruby/wiki/DirectJRubyEmbedding

Further Reading

Using JRuby Bringing Ruby to Java by Charles O Nutter