KEMBAR78
Using Java from Ruby with JRuby IRB | PDF
Using Java from Ruby
                            with JRuby IRB
                                Hiro Asari
                                Engine Yard




Tuesday, June 14, 2011                          1
Why JRuby?

                    • Interactive shell for looking around
                         (without writing lots of code)
                    • Testing frameworks
                    • Ruby on Rails


Tuesday, June 14, 2011                                       2
Assumptions

                    • JRuby 1.6.2 (or 1.7.0.dev)
                    • Java 6 (5 or later; 7 support in the works)
                    • Ruby 1.8


Tuesday, June 14, 2011                                              3

Ruby syntax will be introduced as we go along.
We do not use tricky syntax for this presentation
Starting IRB

                jruby -S irb




    http://jruby.org/tryjruby




Tuesday, June 14, 2011                                                                           4

'-S' tells jruby to look for a script thus named in certain locations (in predefined order) and
execute it. (of course, the usual semantics re: scripts hold here.)

"tryjruby" has some limitations w.r.t. Java integration (obviously)
Loading Java support
                require 'java'




Tuesday, June 14, 2011                          5

Like Java's "import"
Finding Java libraries
                # shell
                export CLASSPATH=…

                jruby -J-cp <classpath> …


                jruby -I lib …

                # in ruby
                $: << File.join(File.dirname(__FILE__),
                 'lib')

Tuesday, June 14, 2011                                           6

Java way, or Ruby way

$: is the global for load paths where Ruby looks for libraries
__FILE__ is a shorthand for "this file"
Loading Java Library
                require 'foo.jar'

                $CLASSPATH << 'foo.jar'




Tuesday, June 14, 2011                          7
Importing Java class
                Bazz = Java::foo.bar.Bazz
                java_import 'foo.bar.Bazz'
                java_import java.lang.System




Tuesday, June 14, 2011                                                                8

Ruby Class names are separated by namespaces, which is delimited by double colons.
Java's built-in classes don't need to be referred to via a String
Ruby class names are constants, the name of which must start with a capital letter.
Referring to Java class
                bazz = Java::foo.bar.Bazz.new
                bazz = Bazz.new # Bazz is already imported




Tuesday, June 14, 2011                                                      9

No parentheses are necessary for Ruby methods, unless ambiguous otherwise
Implementing Java interface
                class Foo
                 include java.lang.Runnable

                 def run
                  puts "foo"
                 end
                end




Tuesday, June 14, 2011                                        10

JRuby works hard to make this simpler, but you get the idea
Calling static methods
                Bazz.method(arg1, arg2)


                java.lang.System.currentTimeMillis




Tuesday, June 14, 2011                               11

This is similar to calling Ruby's class methods
Accessing static fields
                java.lang.System.out
                java.util.logging.Level::INFO




Tuesday, June 14, 2011                            12

Here, "." and "::" are interchangeable
Type conversion
                object.to_java(foo.bar.Bazz)
                "Hello, Richmond!".to_java
                5.to_java(java.lang.Double)




Tuesday, June 14, 2011                                                                    13

For the most part, JRuby converts types for you behind the scenes, so you don’t need to
worry about this; but when you do, you can use this.

Cannot be used for casting to primitives. Sorry.
Invoking overloaded method
                // you need a cast in Java…
                java.lang.System.out.println((char)70)



                java.lang.System.out.java_send :println,
                 [Java::char], 70




Tuesday, June 14, 2011                                                                         14

:println is an example of a Ruby symbol. It is a uniquely identifiable object within the Ruby
runtime. "abc" and "abc" maybe two different Strings, but :abc is always unique.

Notice how we specify the Java primitive "char"
Complex example with Akka
                                  http://akka.io

            “ Akka is the event-driven, the nextand
              generation
                          platform for
                                        scalable
                     fault-tolerant architectures on the JVM   ”

Tuesday, June 14, 2011                                             15
Akka tutorial


                    Compute π using the Madhava-Leibniz series




Tuesday, June 14, 2011                                                16

http://akka.io/docs/akka/1.1.2/intro/getting-started-first-java.html
π


                         = 4(1-1/3+1/5-1/7+1/9-1/11+1/13+…)
                         = 4(1-1/3+1/5-1/7)
                         + 4(1/9-1/11+1/13-1/15)
                         + 4(1/17-1/19+1/21-1/23)
                         +…

Tuesday, June 14, 2011                                        17

http://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80
Does not converge very fast
How does it work?
                         Pi


                         Calculate
                                         Work              Work

                                Master          PiRouter           Worker

                                         Result            Result


Tuesday, June 14, 2011                                                                18

Red: Actors
Green: Messages (POJO)

Akka actors invoke onReceive(Object) method when a message is sent. A router routes
messages between actors.
Akka tutorial

                                       Code reading and demo
                         Java source: http://bit.ly/lTClmr
                         Ruby source: https://gist.github.com/1013227 (Without comments)
                         (See also) https://gist.github.com/1013217




Tuesday, June 14, 2011                                                                     19

See handout
Directory layout
                         akka-tutorial-first
                         ├── akka-reference.conf
                         ├── akka.conf
                         ├── lib/
                         │   ├── akka/
                         │   │    ├── akka-actor-1.1.2.jar
                         │   │    ├── akka-actor-tests-1.1.2.jar
                         │   │    ├── akka-http-1.1.2.jar
                         │   │    ├── akka-remote-1.1.2.jar
                         │   │    ├── akka-slf4j-1.1.2.jar
                         │   │    ├── akka-stm-1.1.2.jar
                         │   │    ├── akka-testkit-1.1.2.jar
                         │   │    ├── akka-typed-actor-1.1.2.jar
                         │   │    ├── aopalliance-1.0.jar
                         │   │    ├── aspectwerkz-2.2.3.jar
                         │   │    ├── commons-codec-1.4.jar
                         │   │    ├── commons-io-2.0.1.jar
                         │   │    ├── dispatch-json_2.9.0-0.8.1.jar
                         │   │    ├── guice-all-2.0.jar
                         │   │    ├── h2-lzf-1.0.jar
                         │   │    ├── jackson-core-asl-1.7.1.jar
                         │   │    ├── jackson-mapper-asl-1.7.1.jar
                         │   │    ├── jsr250-api-1.0.jar
                         │   │    ├── jsr311-api-1.1.jar
                         │   │    ├── multiverse-alpha-0.6.2.jar
                         │   │    ├── netty-3.2.3.Final.jar
                         │   │    ├── objenesis-1.2.jar
                         │   │    ├── protobuf-java-2.3.0.jar
                         │   │    ├── sjson_2.9.0-0.11.jar
                         │   │    └── slf4j-api-1.6.0.jar
                         │   └── scala-library.jar
                         ├── pi.pdf
                         ├── pi.rb
                         └── pi2.rb

                         2 directories, 31 files
Tuesday, June 14, 2011                                                20

http://akka.io/downloads/
http://akka.io/downloads/akka-actors-1.1.2.zip
Move config/* up 1 directory level
Maven integration
                $ jruby -S gem install 
                 mvn:org.clojure:clojure -v 1.2.1
                Successfully installed
                mvn:org.clojure:clojure-1.2.1-java
                1 gem installed




Tuesday, June 14, 2011                                    21

n.b.: artifacts with uncommon versions may not be found
Maven integration
                require 'rubygems'
                require 'java'
                require 'maven/org.clojure/clojure'

                java_import 'clojure.lang.Atom'
                Atom.new(nil)




Tuesday, June 14, 2011                                           22

https://gist.github.com/660804

"require 'maven/foo.bar/bazz.jar'" doesn't work the first time.
Testing frameworks in Ruby
                    • RSpec
                    • Cucumber




Tuesday, June 14, 2011            23
RSpec
         describe Game do
           describe "#score" do
             it "returns 0 for all gutter game" do
               game = Game.new
               20.times { game.roll(0) }
               game.score.should == 0
             end
           end
         end




Tuesday, June 14, 2011                               24

http://relishapp.com/rspec
Cucumber
       # language: en
       Feature: Addition
         In order to avoid silly mistakes
         As a math idiot
         I want to be told the sum of two numbers

             Scenario Outline: Add two numbers
               Given I have entered <input_1> into the calculator
               And I have entered <input_2> into the calculator
               When I press <button>
               Then the result should be <output> on the screen

             Examples:
               | input_1   |   input_2   |   button   |   output   |
               | 20        |   30        |   add      |   50       |
               | 2         |   5         |   add      |   7        |
               | 0         |   40        |   add      |   40       |
Tuesday, June 14, 2011                                                        25

http://cukes.info
https://github.com/cucumber/cucumber/blob/master/examples/i18n/en/features/
addition.feature
IDE

                    • RubyMine
                    • NetBeans (separate Ruby plugin for 7.0)
                    • Eclipse


Tuesday, June 14, 2011                                          26
Other stuff

                    • Ant integration
                    • warbler (generate WAR files)
                    • Ruboto (JRuby on Android)


Tuesday, June 14, 2011                              27
Sponsored plug
                    • JRuby on Rails hosting now available on
                         Engine Yard's AppCloud




Tuesday, June 14, 2011                                          28
JRubyConf 2011
                                  Washington, DC
                                  August 3-5


                           http://jrubyconf.com




Tuesday, June 14, 2011                             29
Thank you!

                                  @hiro_asari
                           hasari@engineyard.com
                            asari.ruby@gmail.com
                         http://github.com/banzaiman




Tuesday, June 14, 2011                                 30
Door prizes!




Tuesday, June 14, 2011        31
Door prizes!




Tuesday, June 14, 2011        32

Using Java from Ruby with JRuby IRB

  • 1.
    Using Java fromRuby with JRuby IRB Hiro Asari Engine Yard Tuesday, June 14, 2011 1
  • 2.
    Why JRuby? • Interactive shell for looking around (without writing lots of code) • Testing frameworks • Ruby on Rails Tuesday, June 14, 2011 2
  • 3.
    Assumptions • JRuby 1.6.2 (or 1.7.0.dev) • Java 6 (5 or later; 7 support in the works) • Ruby 1.8 Tuesday, June 14, 2011 3 Ruby syntax will be introduced as we go along. We do not use tricky syntax for this presentation
  • 4.
    Starting IRB jruby -S irb http://jruby.org/tryjruby Tuesday, June 14, 2011 4 '-S' tells jruby to look for a script thus named in certain locations (in predefined order) and execute it. (of course, the usual semantics re: scripts hold here.) "tryjruby" has some limitations w.r.t. Java integration (obviously)
  • 5.
    Loading Java support require 'java' Tuesday, June 14, 2011 5 Like Java's "import"
  • 6.
    Finding Java libraries # shell export CLASSPATH=… jruby -J-cp <classpath> … jruby -I lib … # in ruby $: << File.join(File.dirname(__FILE__), 'lib') Tuesday, June 14, 2011 6 Java way, or Ruby way $: is the global for load paths where Ruby looks for libraries __FILE__ is a shorthand for "this file"
  • 7.
    Loading Java Library require 'foo.jar' $CLASSPATH << 'foo.jar' Tuesday, June 14, 2011 7
  • 8.
    Importing Java class Bazz = Java::foo.bar.Bazz java_import 'foo.bar.Bazz' java_import java.lang.System Tuesday, June 14, 2011 8 Ruby Class names are separated by namespaces, which is delimited by double colons. Java's built-in classes don't need to be referred to via a String Ruby class names are constants, the name of which must start with a capital letter.
  • 9.
    Referring to Javaclass bazz = Java::foo.bar.Bazz.new bazz = Bazz.new # Bazz is already imported Tuesday, June 14, 2011 9 No parentheses are necessary for Ruby methods, unless ambiguous otherwise
  • 10.
    Implementing Java interface class Foo include java.lang.Runnable def run puts "foo" end end Tuesday, June 14, 2011 10 JRuby works hard to make this simpler, but you get the idea
  • 11.
    Calling static methods Bazz.method(arg1, arg2) java.lang.System.currentTimeMillis Tuesday, June 14, 2011 11 This is similar to calling Ruby's class methods
  • 12.
    Accessing static fields java.lang.System.out java.util.logging.Level::INFO Tuesday, June 14, 2011 12 Here, "." and "::" are interchangeable
  • 13.
    Type conversion object.to_java(foo.bar.Bazz) "Hello, Richmond!".to_java 5.to_java(java.lang.Double) Tuesday, June 14, 2011 13 For the most part, JRuby converts types for you behind the scenes, so you don’t need to worry about this; but when you do, you can use this. Cannot be used for casting to primitives. Sorry.
  • 14.
    Invoking overloaded method // you need a cast in Java… java.lang.System.out.println((char)70) java.lang.System.out.java_send :println, [Java::char], 70 Tuesday, June 14, 2011 14 :println is an example of a Ruby symbol. It is a uniquely identifiable object within the Ruby runtime. "abc" and "abc" maybe two different Strings, but :abc is always unique. Notice how we specify the Java primitive "char"
  • 15.
    Complex example withAkka http://akka.io “ Akka is the event-driven, the nextand generation platform for scalable fault-tolerant architectures on the JVM ” Tuesday, June 14, 2011 15
  • 16.
    Akka tutorial Compute π using the Madhava-Leibniz series Tuesday, June 14, 2011 16 http://akka.io/docs/akka/1.1.2/intro/getting-started-first-java.html
  • 17.
    π = 4(1-1/3+1/5-1/7+1/9-1/11+1/13+…) = 4(1-1/3+1/5-1/7) + 4(1/9-1/11+1/13-1/15) + 4(1/17-1/19+1/21-1/23) +… Tuesday, June 14, 2011 17 http://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80 Does not converge very fast
  • 18.
    How does itwork? Pi Calculate Work Work Master PiRouter Worker Result Result Tuesday, June 14, 2011 18 Red: Actors Green: Messages (POJO) Akka actors invoke onReceive(Object) method when a message is sent. A router routes messages between actors.
  • 19.
    Akka tutorial Code reading and demo Java source: http://bit.ly/lTClmr Ruby source: https://gist.github.com/1013227 (Without comments) (See also) https://gist.github.com/1013217 Tuesday, June 14, 2011 19 See handout
  • 20.
    Directory layout akka-tutorial-first ├── akka-reference.conf ├── akka.conf ├── lib/ │ ├── akka/ │ │ ├── akka-actor-1.1.2.jar │ │ ├── akka-actor-tests-1.1.2.jar │ │ ├── akka-http-1.1.2.jar │ │ ├── akka-remote-1.1.2.jar │ │ ├── akka-slf4j-1.1.2.jar │ │ ├── akka-stm-1.1.2.jar │ │ ├── akka-testkit-1.1.2.jar │ │ ├── akka-typed-actor-1.1.2.jar │ │ ├── aopalliance-1.0.jar │ │ ├── aspectwerkz-2.2.3.jar │ │ ├── commons-codec-1.4.jar │ │ ├── commons-io-2.0.1.jar │ │ ├── dispatch-json_2.9.0-0.8.1.jar │ │ ├── guice-all-2.0.jar │ │ ├── h2-lzf-1.0.jar │ │ ├── jackson-core-asl-1.7.1.jar │ │ ├── jackson-mapper-asl-1.7.1.jar │ │ ├── jsr250-api-1.0.jar │ │ ├── jsr311-api-1.1.jar │ │ ├── multiverse-alpha-0.6.2.jar │ │ ├── netty-3.2.3.Final.jar │ │ ├── objenesis-1.2.jar │ │ ├── protobuf-java-2.3.0.jar │ │ ├── sjson_2.9.0-0.11.jar │ │ └── slf4j-api-1.6.0.jar │ └── scala-library.jar ├── pi.pdf ├── pi.rb └── pi2.rb 2 directories, 31 files Tuesday, June 14, 2011 20 http://akka.io/downloads/ http://akka.io/downloads/akka-actors-1.1.2.zip Move config/* up 1 directory level
  • 21.
    Maven integration $ jruby -S gem install mvn:org.clojure:clojure -v 1.2.1 Successfully installed mvn:org.clojure:clojure-1.2.1-java 1 gem installed Tuesday, June 14, 2011 21 n.b.: artifacts with uncommon versions may not be found
  • 22.
    Maven integration require 'rubygems' require 'java' require 'maven/org.clojure/clojure' java_import 'clojure.lang.Atom' Atom.new(nil) Tuesday, June 14, 2011 22 https://gist.github.com/660804 "require 'maven/foo.bar/bazz.jar'" doesn't work the first time.
  • 23.
    Testing frameworks inRuby • RSpec • Cucumber Tuesday, June 14, 2011 23
  • 24.
    RSpec describe Game do describe "#score" do it "returns 0 for all gutter game" do game = Game.new 20.times { game.roll(0) } game.score.should == 0 end end end Tuesday, June 14, 2011 24 http://relishapp.com/rspec
  • 25.
    Cucumber # language: en Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers Scenario Outline: Add two numbers Given I have entered <input_1> into the calculator And I have entered <input_2> into the calculator When I press <button> Then the result should be <output> on the screen Examples: | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 | Tuesday, June 14, 2011 25 http://cukes.info https://github.com/cucumber/cucumber/blob/master/examples/i18n/en/features/ addition.feature
  • 26.
    IDE • RubyMine • NetBeans (separate Ruby plugin for 7.0) • Eclipse Tuesday, June 14, 2011 26
  • 27.
    Other stuff • Ant integration • warbler (generate WAR files) • Ruboto (JRuby on Android) Tuesday, June 14, 2011 27
  • 28.
    Sponsored plug • JRuby on Rails hosting now available on Engine Yard's AppCloud Tuesday, June 14, 2011 28
  • 29.
    JRubyConf 2011 Washington, DC August 3-5 http://jrubyconf.com Tuesday, June 14, 2011 29
  • 30.
    Thank you! @hiro_asari hasari@engineyard.com asari.ruby@gmail.com http://github.com/banzaiman Tuesday, June 14, 2011 30
  • 31.
  • 32.