using java from ruby with jruby irb
DESCRIPTION
Slides to my talk at Richmond JUG + Central Virginia Ruby Enthusiasts' Group on June 14, 2011.TRANSCRIPT
Using Java from Ruby with JRuby IRB
Hiro AsariEngine Yard
1Tuesday, June 14, 2011
Why JRuby?
• Interactive shell for looking around (without writing lots of code)
• Testing frameworks
• Ruby on Rails
2Tuesday, June 14, 2011
Assumptions
• JRuby 1.6.2 (or 1.7.0.dev)
• Java 6 (5 or later; 7 support in the works)
• Ruby 1.8
3Tuesday, June 14, 2011
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
4Tuesday, June 14, 2011
'-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'
5Tuesday, June 14, 2011
Like Java's "import"
Finding Java libraries
# in ruby$: << File.join(File.dirname(__FILE__),'lib')
jruby -I lib …
jruby -J-cp <classpath> …
# shellexport CLASSPATH=…
6Tuesday, June 14, 2011
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'
7Tuesday, June 14, 2011
Importing Java class
Bazz = Java::foo.bar.Bazzjava_import 'foo.bar.Bazz'java_import java.lang.System
8Tuesday, June 14, 2011
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 StringRuby class names are constants, the name of which must start with a capital letter.
Referring to Java class
bazz = Java::foo.bar.Bazz.newbazz = Bazz.new # Bazz is already imported
9Tuesday, June 14, 2011
No parentheses are necessary for Ruby methods, unless ambiguous otherwise
Implementing Java interface
class Fooinclude java.lang.Runnable
def runputs "foo"
endend
10Tuesday, June 14, 2011
JRuby works hard to make this simpler, but you get the idea
Calling static methods
Bazz.method(arg1, arg2)
java.lang.System.currentTimeMillis
11Tuesday, June 14, 2011
This is similar to calling Ruby's class methods
Accessing static fields
java.lang.System.outjava.util.logging.Level::INFO
12Tuesday, June 14, 2011
Here, "." and "::" are interchangeable
Type conversion
object.to_java(foo.bar.Bazz)"Hello, Richmond!".to_java5.to_java(java.lang.Double)
13Tuesday, June 14, 2011
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.
java.lang.System.out.java_send :println,[Java::char], 70
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
14Tuesday, June 14, 2011
: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 Akkahttp://akka.io
Akka is the platform for the next generation event-driven, scalable and fault-tolerant architectures on the JVM
“”
15Tuesday, June 14, 2011
Akka tutorial
Compute π using the Madhava-Leibniz series
16Tuesday, June 14, 2011
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)+ …
17Tuesday, June 14, 2011
http://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80Does not converge very fast
How does it work?
Result
WorkWork
PiRouterMaster Worker
Calculate
Result
Pi
18Tuesday, June 14, 2011
Red: ActorsGreen: 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/lTClmrRuby source: https://gist.github.com/1013227 (Without comments)(See also) https://gist.github.com/1013217
19Tuesday, June 14, 2011
See handout
Directory layoutakka-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
20Tuesday, June 14, 2011
http://akka.io/downloads/http://akka.io/downloads/akka-actors-1.1.2.zipMove 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-java1 gem installed
21Tuesday, June 14, 2011
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)
22Tuesday, June 14, 2011
https://gist.github.com/660804
"require 'maven/foo.bar/bazz.jar'" doesn't work the first time.
Testing frameworks in Ruby
• RSpec
• Cucumber
23Tuesday, June 14, 2011
RSpecdescribe 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 endend
24Tuesday, June 14, 2011
http://relishapp.com/rspec
Cucumber# language: enFeature: 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 |
25Tuesday, June 14, 2011
http://cukes.infohttps://github.com/cucumber/cucumber/blob/master/examples/i18n/en/features/addition.feature
IDE
• RubyMine
• NetBeans (separate Ruby plugin for 7.0)
• Eclipse
26Tuesday, June 14, 2011
Other stuff
• Ant integration
• warbler (generate WAR files)
• Ruboto (JRuby on Android)
27Tuesday, June 14, 2011
Sponsored plug
• JRuby on Rails hosting now available on Engine Yard's AppCloud
28Tuesday, June 14, 2011
JRubyConf 2011
Washington, DCAugust 3-5
http://jrubyconf.com
29Tuesday, June 14, 2011
Door prizes!
31Tuesday, June 14, 2011
Door prizes!
32Tuesday, June 14, 2011