Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Connecting the Worlds of Java and Ruby with JRuby
1. Connecting
Java and Ruby
Nick Sieger :: December 14, 2010
To begin at 10 AM Pacific.
Audio or visual issues?
Call 24/7 WebEx Tech Support (866) 229-3239
Slides: http://j.mp/ey-jruby-connecting
12. Ruby: Duck-Typing
def area(width = 10, height = 2 * width)
width * height
end
p area # => 200
p area 5 # => 50
p area 5, 20 # => 100
p area "10", 4 # => ?
13. Ruby: Duck-Typing
p area "10", 4 # => "10101010"
# From Ruby API docs:
# String#*(num)
#
# Returns a new String containing num copies of
# the receiver.
#
# "Ho! " * 3 #=> "Ho! Ho! Ho! "
area true, false
# => NoMethodError: undefined method `*' for
# true:TrueClass
15. Ruby: Blocks
list = [1, 2, 3, 4]
list.each {|n| puts n }
Ruby
list.each do |n|
puts n
end
List<Integer> list = Arrays.asList(1, 2, 3, 4);
Java for (Integer n : list) {
System.out.println(n);
}
16. Ruby: Blocks
list.shuffle!
# => [3, 1, 4, 2]
Ruby
p list.sort {|a, b| b <=> a }
# => [4, 3, 2, 1]
Collections.shuffle(list);
Collections.sort(list, new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
Java return b > a ? 1 : (b < a ? -1 : 0);
}
});
System.out.println(list);
17. Ruby: Blocks
File.open(__FILE__) do |file|
file.each_line do |line|
Ruby puts line
end
end
BufferedReader file =
new BufferedReader(new FileReader("Blocks.java"));
try {
String line;
while ((line = buf.readLine()) != null) {
Java System.out.println(line);
}
} finally {
file.close();
}
18. Ruby: Open Classes
msg = "Scramble this so you can't read it!"
msg.rot13!
# => NoMethodError: undefined method `rot13!' for
# "Scramble this so you can't read it!":String
19. Ruby: Open Classes
class String
def rot13!
0.upto(length - 1) do |i|
case self[i]
when ?a..?z
self[i] = ?a + ((self[i] - ?a) + 13) % 26
when ?A..?Z
self[i] = ?A + ((self[i] - ?A) + 13) % 26
end
end
self
end
end
20. Ruby: Open Classes
puts msg.rot13!
# => "Fpenzoyr guvf fb lbh pna'g ernq vg!"
puts msg.rot13!
# => "Scramble this so you can't read it!"
26. Ruby: Summary
• Organize code the way you want
Dynamic and Open • Associate behavior with the correct class
• No more “Util” classes
• Express code intent succinctly
Flexible • Strip away unnecessary ceremony
• Try out code and get instant feedback
Interactive • Learn by doing
• Productivity gains lead to increased pleasure
Happy • Enjoy crafting clean code
31. Rails: Convention over Configuration
URL GET /people
resources :people
Routing
#=> people#index
# app/controllers/people_controller.rb
class PeopleController < ApplicationController
def index
Controller
@people = Person.all
end
end
# app/models/person.rb
Model class Person < ActiveRecord::Base
end
View app/views/people/index.html.erb
32. Rails: Defaults with Choices
Default Alternatives
DataMapper, MongoMapper,
ORM ActiveRecord Sequel, Any object with
ActiveModel
HAML, Builder XML,
View Templates ERb Markaby, RedCloth (Textile),
BlueCloth (Markdown)
JavaScript Framework Prototype jQuery
MySQL, PostgreSQL, Oracle,
Database SQLite3
more via JRuby + JDBC
Test Framework Test::Unit RSpec, Cucumber
36. Rails: New Application
$ rails new coolapp -m http://jruby.org
create
create README
create Rakefile
...
37. Rails: Dependencies with Bundler
$ cd coolapp
$ bundle install
Fetching source index for http://rubygems.org/
Using rake (0.8.7)
Using abstract (1.0.0)
...
Using rails (3.0.3)
Your bundle is complete!
40. Rails: Start Dev Server
$ rails server
=> Booting WEBrick
=> Rails 3.0.3 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-12-13 20:11:28] INFO WEBrick 1.3.1
[2010-12-13 20:11:28] INFO ruby 1.8.7 (2010-12-10) [java]
[2010-12-13 20:11:28] INFO WEBrick::HTTPServer#start: pid=21022 port=3000
45. Routes
# config/routes.rb (abbreviated)
Diaspora::Application.routes.draw do
# ...
resources :photos, :except => [:index]
#...
root :to => 'home#show'
end
46. Rails: RESTful Routes
Verb Path Action Used for
display a list of all
GET /photos index
photos
return an HTML form for
GET /photos/new new
creating a new photo
POST /photos create create a new photo
GET /photos/:id show display a specific photo
return an HTML form for
GET /photos/:id/edit edit
editing a photo
PUT /photos/:id update update a specific photo
DELETE /photos/:id destroy delete a specific photo
47. Rails: RESTful Routes
Verb Path Action Used for
display a list of all
GET /photos index
:except => [:index] photos
return an HTML form for
GET /photos/new new
creating a new photo
POST /photos create create a new photo
GET /photos/:id show display a specific photo
return an HTML form for
GET /photos/:id/edit edit
editing a photo
PUT /photos/:id update update a specific photo
DELETE /photos/:id destroy delete a specific photo
48. Controller
# app/controllers/photos_controller.rb (abbr.)
class PhotosController < ApplicationController
respond_to :html
respond_to :json, :only => :show
def show
@photo = current_user.find_visible_post_by_id params[:id]
# ...
respond_with @photo
end
end
49. Model
# app/models/photo.rb (abbreviated)
class Photo < Post
include MongoMapper::Document
require 'carrierwave/orm/mongomapper'
mount_uploader :image, ImageUploader
key :caption, String
key :status_message_id, ObjectId
belongs_to :status_message
validate :ownership_of_status_message
before_destroy :ensure_user_picture
end
53. Rails: Summary
• No wasting time deciding where to put something
Place for Everything &
• Shared conventions get team members up to
Conventions speed quickly
• No wasted effort getting started
Defaults with Choices • Easy to add/change components later
• Development: “code and reload”
Environments • Test: disposable data
• Production: cache and optimize
• Mature framework, frequent updates
Community • Rich catalog of plugins
• Rails programmers are in-demand
55. Getting JRuby
OS How to get
•http://jruby.org/download
All •Ruby Version Manager (RVM)
http://rvm.beginrescueend.com/
Windows •Installer from http://jruby.org/download
Mac OS X
•Homebrew - brew install jruby
•MacPorts - port install jruby
Ubuntu/Debian •apt-get install jruby (may not be up-to-date,
may need multiverse)
Fedora/RHEL/Centos •yum install jruby (may not be up-to-date)
Gentoo •emerge dev-java/jruby (may be old)
http://wiki.jruby.org/JRubyDistributions
56. Using JRuby
$ jruby script.rb Run a standalone script
$ jruby -S gem ... Run Rubygems, IRB, or an installed
gem (e.g, rake or rails)
$ jruby -J-Xmx1G ... Pass arguments to the JVM
$ jruby --help Get help
$ jruby --properties
57. Access Java from JRuby
require 'java'
require 'rubygems'
require 'flying_saucer'
java_import org.xhtmlrenderer.pdf.ITextRenderer
document = <<-HTML
<html><body><h1>Hello Flying Saucer!</h1></body></html>
HTML
File.open("doc.pdf", "wb") do |out|
renderer = ITextRenderer.new
renderer.set_document_from_string document
renderer.layout
renderer.create_pdf out.to_outputstream
end
system("open doc.pdf")
Tip: jruby -S gem install flying_saucer to try this example.
60. Access Java from JRuby
require 'rubygems'
require 'flying_saucer'
Loads Flying Saucer classes from Rubygems
61. Access Java from JRuby
java_import org.xhtmlrenderer.pdf.ITextRenderer
Imports ITextRenderer class
62. Access Java from JRuby
Ruby renderer = ITextRenderer.new
Java ITextRenderer renderer = new ITextRenderer();
Create new ITextRenderer
63. Access Java from JRuby
Ruby renderer.set_document_from_string document
Java renderer.setDocumentFromString(document);
Set up the document
64. Access Java from JRuby
File.open("doc.pdf", "wb") do |out|
...
renderer.create_pdf out.to_outputstream
end
Create PDF with explicit conversion
from Ruby IO to Java OutputStream
65. Integrating into Rails
Mime::Type.register 'application/pdf', :pdf
Register PDF mime type in Rails
66. Integrating into Rails
class PhotosController
private
def pdf_to_string
io = StringIO.new
content = render_to_string
renderer = ITextRenderer.new
renderer.set_document_from_string(content)
renderer.layout
renderer.create_pdf(io.to_outputstream)
io.string
end
end
67. Integrating into Rails
class PhotosController
def index
@photos = Photos.all
respond_to do |format|
format.html
format.pdf do
send_data pdf_to_string, :filename => pdf_name + ".pdf",
:type => 'application/pdf', :disposition => 'inline'
end
end
end
end
68. Integrating into Rails
http://example.com/photos HTML view of photo listing
http://example.com/photos.pdf Inline PDF of photo listing
69. Rails 3 and JRuby
http://weblog.rubyonrails.org/2010/8/29/rails-3-0-it-s-done
71. Rails Performance
http://github.com/wycats/rails-simple-benches
rails-simple N = 10,000 rails-simple N = 10,000
15000 120000
ruby 1.9.2 ruby 1.9.2
12500 jruby-head client 100000 jruby-head client
10000 jruby-head server 80000 jruby-head server
7500 60000
5000 40000
2500 20000
0 0
partial_100 coll_100 uniq_100 diff_100
ad
x
1
al
10
10
de
e_
rti
_
ll_
he
at
al
pa
in
co
er
rti
pl
ov
pa
m
te
72. JRuby Deployment
Ruby servers WAR files PaaS
WEBrick GlassFish EY AppCloud
GF Gem Tomcat AppEngine
Trinidad JBoss SteamCannon
73. Warbler
INSTALL gem install warbler
• Create a Java EE .war file from a Rails application
• “Looks like Java” to the ops staff
deploy
Rails
warble app.war to java
app
appserver
74. JRuby-Rack Servlet Filter
/home.jsp:
Servlet JSP
dispatch
pass-thru
/home.jsp /home/index:
JRuby-Rack 404
RackFilter
doFilter
On 404:
/home/index
Rails or any /home/index:
Rack-based Rails
application Home-
Controller
84. Built Environment Metaphor
Metaphor Use Ruby, JRuby, and Rails to...
• Build a new facade faster with modern technology
Sagrada Familia • Scaffold portions of the application during refactoring
• Revive a languishing project by putting a new face on it
Ryugyong Hotel
• Reinforce business rules with a DSL
Seismic retrofit • Harden security around an existing application
Szkieletor • Find novel uses for otherwise abandoned code
85. JRuby Stories: LinkedIn Signal
• High-volume social networking application
• http://www.infoq.com/articles/linkedin-scala-jruby-voldemort
• http://blog.linkedin.com/2010/09/29/linkedin-signal/
86. JRuby Stories: Tracker
• Protecting the world from terrorists!
• Export Control workflow system
• Used by US State dept. and other countries
• JRuby, Rails and legacy Java
• http://trackernet.org
• Making the World Safe For Democracy
• David Bock, Arild Shirazi
• http://vimeo.com/16270284
87. JRuby Events
• JRubyConf 2009
• free event following RubyConf
• ~200 attendees
• JRubyConf 2010
• standalone conference
• 150 attendees
• JRuby meetups in SF Bay Area
• http://www.meetup.com/SF-Bay-
Area-JRuby-Meetup/
90. Resources
• Contact me: Nick Sieger – nsieger@engineyard.com
• These slides: http://j.mp/ey-jruby-connecting
• JRuby.org – http://jruby.org/
• JRubyConf 2010 videos
• http://j.mp/jrubyconf-2010-videos
• EY Blog: Resources for Getting Started with Ruby on Rails
• http://j.mp/ey-getting-started-rails
• Rails for Zombies
• http://railsforzombies.org/
91. Zero to Rails 3
Virtual Training
January 24-27, 2011
http://www.eventbee.com/view/zero-to-rails-3
training@engineyard.com
Immediately following (optional):
Engine Yard AppCloud Demo
with Danish Khan
15-20 minute overview of AppCloud