Connecting the Worlds of Java and Ruby with JRuby

Post on 10-May-2015

5.202 views 3 download

description

Slides from Engine Yard/Terremark sponsored webinar "Connecting the worlds of Java and Ruby with JRuby".

Transcript of Connecting the Worlds of Java and Ruby with JRuby

ConnectingJava and RubyNick Sieger :: December 14, 2010

To begin at 10 AM Pacific.Audio or visual issues?Call 24/7 WebEx Tech Support (866) 229-3239Slides: http://j.mp/ey-jruby-connecting

ConnectingJava and RubyNick Sieger :: December 14, 2010

http://www.flickr.com/photos/hb2/288721287/

JRuby: Bridge Between Two Worlds

Bridges facilitate...

Movement Cross-pollination Collaboration Trading

Bridge from Ruby to Java

http://www.flickr.com/photos/the_rev/2295096211/http://www.flickr.com/photos/orbitaljoe/4038901965/

Bridge from Java to Ruby

http://www.flickr.com/photos/design-dog/1268749868/

Bridge from Enterprise to Cloud

http://www.flickr.com/photos/nzdave/347532488/ http://www.flickr.com/photos/ancawonka/65927497/

Bridge from Legacy to Greenfield

http://www.flickr.com/photos/cobalt/318394059/ http://www.flickr.com/photos/13010608@N02/2441101211/

RubyDynamic language of the cloud

A word aboutscripting...

It’s for kiddies.

http://www.flickr.com/photos/listenmissy/4869202176/

Ruby: Dynamic, Object-Oriented

Ruby: Duck-Typing

def area(width = 10, height = 2 * width) width * heightend

p area # => 200p area 5 # => 50p area 5, 20 # => 100p area "10", 4 # => ?

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

Ruby: Flexible Syntax

def set_options(env, opts)end

set_options(:production, {"caching" => "on", "debug" => "false"})

set_options(:production, "caching" => "on", "debug" => "false")

set_options :production, {"caching" => "on", "debug" => "false"}

set_options :production, "caching" => "on", "debug" => "false"

Ruby: Blocks

Ruby

Java

list = [1, 2, 3, 4]

list.each {|n| puts n }

list.each do |n| puts nend

List<Integer> list = Arrays.asList(1, 2, 3, 4);

for (Integer n : list) { System.out.println(n);}

Ruby: Blocks

Ruby

Java

list.shuffle! # => [3, 1, 4, 2]

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) { return b > a ? 1 : (b < a ? -1 : 0); } });

System.out.println(list);

Ruby: Blocks

Ruby

Java

File.open(__FILE__) do |file| file.each_line do |line| puts line endend

BufferedReader file = new BufferedReader(new FileReader("Blocks.java"));try { String line; while ((line = buf.readLine()) != null) { System.out.println(line); }} finally { file.close();}

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

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 endend

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!"

Ruby: Interactive

$ irbirb(main):001:0> list = [1, 2, 3, 4]=> [1, 2, 3, 4]irb(main):002:0> list.shuffle.map {|x| x + rand(10)}.sort=> [6, 7, 11, 13]irb(main):003:0> list=> [1, 2, 3, 4]

Ruby: Interactive

irb(main):004:0> require 'irb/completion'=> trueirb(main):005:0> list.<TAB>Display all 138 possibilities? (y or n) irb(main):005:0> list.d<TAB>list.delete list.delete_at list.delete_if list.detect list.display list.drop list.drop_while list.dup

Ruby: Developer Happiness

=

RubyGems

Testing in Ruby

RSpechttp://cukes.info/http://rspec.info/

Ruby: Summary

Dynamic and Open• Organize code the way you want• Associate behavior with the correct class• No more “Util” classes

Flexible • Express code intent succinctly• Strip away unnecessary ceremony

Interactive • Try out code and get instant feedback• Learn by doing

Happy • Productivity gains lead to increased pleasure• Enjoy crafting clean code

RailsDynamic framework of the cloud

Rails: Opinionated Framework

Place foreverything

Request-basedMVC

Conventionover

Configuration

Defaultswith

Choices

Rails: Place for All Your Code

application code

configuration & environments

routes (URL structure)

database migrations

static assets(images, stylesheets, javascript)

tests

Rails: Request-based MVC

View

ActionView

Controller

ActionController

Model

ActiveRecord

Request

Database

Response

Routing

ActionDispatch

URL GET /people

Routingresources :people #=> people#index

Controller

# app/controllers/people_controller.rbclass PeopleController < ApplicationController def index @people = Person.all endend

Model# app/models/person.rbclass Person < ActiveRecord::Baseend

View app/views/people/index.html.erb

Rails: Convention over Configuration

Rails: Defaults with Choices

Default Alternatives

ORM

View Templates

JavaScript Framework

Database

Test Framework

ActiveRecordDataMapper, MongoMapper, Sequel, Any object with ActiveModel

ERbHAML, Builder XML, Markaby, RedCloth (Textile), BlueCloth (Markdown)

Prototype jQuery

SQLite3MySQL, PostgreSQL, Oracle, more via JRuby + JDBC

Test::Unit RSpec, Cucumber

Why Rails?

http://j.mp/raible-jvm-frameworks

© 2010, Raible DesignsImages by Stuck in Customs - http://www.flickr.com/photos/stuckincustoms

© 2010 Raible Designs

COMPARING JVM WEB FRAMEWORKS

Matt Raiblehttp://raibledesigns.com

Why Rails?

Projectmaturity

InformationBooks,Docs

Developmentspeed

Availableskilled

developers

Consider...

Installing RailsINSTALL gem install rails

Rails: New Application

$ rails new coolapp -m http://jruby.org create create README create Rakefile ...

Rails: Dependencies with Bundler

$ cd coolapp

$ bundle installFetching 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!

Rails: Generate Scaffolding

$ rails generate scaffold person email:string password:string invoke active_record create db/migrate/20101214020707_create_people.rb create app/models/person.rb invoke test_unit create test/unit/person_test.rb create test/fixtures/people.yml route resources :people ...

Rails: Migrate Database

$ rake db:migrate(in /Users/nicksieger/Projects/rails/coolapp)== CreatePeople: migrating ===========================-- create_table(:people) -> 0.0040s -> 0 rows== CreatePeople: migrated (0.0040s) ==================

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

Rails: First Page

Rails: Console

$ rails consoleLoading development environment (Rails 3.0.3)irb(main):001:0> Person.create :email => "nsieger@engineyard.com", :password => "rails" => #<Person id: 1, email: "nsieger@engineyard.com", password: "rails", created_at: "2010-12-14 02:21:11", updated_at: "2010-12-14 02:21:11">

Real-world Rails

Routes

# config/routes.rb (abbreviated)Diaspora::Application.routes.draw do # ... resources :photos, :except => [:index]

#... root :to => 'home#show'end

Verb Path Action Used for

GET /photos indexdisplay a list of all photos

GET /photos/new newreturn an HTML form for creating a new photo

POST /photos create create a new photo

GET /photos/:id show display a specific photo

GET /photos/:id/edit editreturn an HTML form for editing a photo

PUT /photos/:id update update a specific photo

DELETE /photos/:id destroy delete a specific photo

Rails: RESTful Routes

Verb Path Action Used for

GET /photos indexdisplay a list of all photos

GET /photos/new newreturn an HTML form for creating a new photo

POST /photos create create a new photo

GET /photos/:id show display a specific photo

GET /photos/:id/edit editreturn an HTML form for editing a photo

PUT /photos/:id update update a specific photo

DELETE /photos/:id destroy delete a specific photo

Rails: RESTful Routes

:except => [:index]

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 endend

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_pictureend

View

Rendering photo list

HAML View

-# app/views/people/show.html.haml (abbr.).span-15.last %h4 = t('_photos') = render 'photos/index', :photos => @posts

-# app/views/photos/_index.html.haml (abbr.)#thumbnails.span-15.last - for photo in photos = link_to photo.url(:thumb_medium), photo_path(photo)

Rendered HTML View

<div class='span-15 last'> <h4> photos </h4> <div class='span-15 last' id='thumbnails'> <a href="/photos/4d0694d..."><img src="/uploads/images/..." /></a> <a href="/photos/4d06949..."><img src="/uploads/images/..." /></a> <a href="/photos/4d068b2..."><img src="/uploads/images/..." /></a> </div></div>

Rails: Summary

Place for Everything &Conventions

• No wasting time deciding where to put something• Shared conventions get team members up to speed quickly

Defaults with Choices • No wasted effort getting started• Easy to add/change components later

Environments• Development: “code and reload”• Test: disposable data• Production: cache and optimize

Community• Mature framework, frequent updates• Rich catalog of plugins• Rails programmers are in-demand

Dynamic toolkit of the cloud

Getting JRuby

OS How to get

All•http://jruby.org/download•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

Using JRuby

$ jruby script.rb

$ jruby -S gem ...

$ jruby -J-Xmx1G ...

$ jruby --help$ jruby --properties

Run a standalone script

Run Rubygems, IRB, or an installed gem (e.g, rake or rails)

Pass arguments to the JVM

Get help

Access Java from JRuby

Tip: jruby -S gem install flying_saucer to try this example.

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_outputstreamend

system("open doc.pdf")

Access Java from JRuby

$ jruby saucer.rb

Access Java from JRuby

require 'java'

Loads Java Integration

Access Java from JRuby

require 'rubygems'require 'flying_saucer'

Loads Flying Saucer classes from Rubygems

Access Java from JRuby

Imports ITextRenderer class

java_import org.xhtmlrenderer.pdf.ITextRenderer

Access Java from JRuby

Create new ITextRenderer

Ruby

Java

renderer = ITextRenderer.new

ITextRenderer renderer = new ITextRenderer();

Access Java from JRuby

Set up the document

Ruby

Java

renderer.set_document_from_string document

renderer.setDocumentFromString(document);

Access Java from JRuby

Create PDF with explicit conversion from Ruby IO to Java OutputStream

File.open("doc.pdf", "wb") do |out| ... renderer.create_pdf out.to_outputstreamend

Integrating into Rails

Mime::Type.register 'application/pdf', :pdf

Register PDF mime type in Rails

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 endend

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 endend

Integrating into Rails

http://example.com/photos

http://example.com/photos.pdf

HTML view of photo listing

Inline PDF of photo listing

Rails 3 and JRuby

http://weblog.rubyonrails.org/2010/8/29/rails-3-0-it-s-done

http://ci.jruby.org/

Rails Performance

0

2500

5000

7500

10000

12500

15000

over

head

index

tem

plate_

1

partia

l

partia

l_10

coll_

10

rails-simple N = 10,000

ruby 1.9.2jruby-head clientjruby-head server

0

20000

40000

60000

80000

100000

120000

partial_100 coll_100 uniq_100 diff_100

rails-simple N = 10,000

ruby 1.9.2jruby-head clientjruby-head server

http://github.com/wycats/rails-simple-benches

JRuby Deployment

Ruby servers

WEBrick

GF Gem

Trinidad

WAR files

GlassFish

Tomcat

JBoss

PaaS

EY AppCloud

AppEngine

SteamCannon

Warbler

Railsapp warble app.war

deployto java

appserver

•Create a Java EE .war file from a Rails application• “Looks like Java” to the ops staff

INSTALL gem install warbler

JRuby-Rack Servlet Filter

JRuby-RackRackFilterdoFilter

Servlet dispatchpass-thru

On 404:Rails or anyRack-basedapplication

/home.jsp

/home/index

/home.jsp:JSP

/home/index:Rails

Home-Controller

/home/index:404

Hybrid Rails/Java Webapp

RailsMVC

ActionDispatchActionDispatchActionDispatch

RailsMVC ActionController/ActionViewActionController/ActionViewActionController/ActionViewRailsMVC

ActiveModelActiveModelActiveModel

JavaPOJOs

JDBCDataSource

SOAPinterface

Tools

http://redcareditor.com/

http://www.jetbrains.com/ruby/

http://netbeans.org/

Enterprise Software

Evolving and adapting long-running projects with legacy codebases

http://en.wikipedia.org/wiki/File:Sagrada_Familia_01.jpg

Sagrada Família, Barcelona, Spain

http://www.flickr.com/photos/koocheekoo/38407225/http://w

ww.flickr.com

/photos/27649557@N07/5000528445/

http://www.flickr.com/photos/gpaumier/446059442/ http://www.flickr.com/photos/ilm/12831049/

nativityfacade

passionfacade

scaffolded interior

http://en.wikipedia.org/w

iki/F

ile:Ryugyong_Ho

tel_-_May_2005.JPG

http://en.wikipedia.org/w

iki/File:Ryugyong_Hotel_October_2010.jpg

Ryugyuong Hotel,North Korea2005 2010

http://www.flickr.com

/photos/bazylek/3194294047/http://en.wikipedia.org/w

iki/F

ile:Szkieleteor_in_krakow

.JPG

Szkieletor,Kraków, Poland

Built Environment Metaphor

Metaphor Use Ruby, JRuby, and Rails to...

Sagrada Familia • Build a new facade faster with modern technology• Scaffold portions of the application during refactoring

Ryugyong Hotel • Revive a languishing project by putting a new face on it

Seismic retrofit• Reinforce business rules with a DSL• Harden security around an existing application

Szkieletor • Find novel uses for otherwise abandoned code

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/

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

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/

Using JRuby

JRuby on AppCloud

JRuby +AppCloud

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/

Zero to Rails 3Virtual TrainingJanuary 24-27, 2011 http://www.eventbee.com/view/zero-to-rails-3

training@engineyard.com

Immediately following (optional):Engine Yard AppCloud Demowith Danish Khan15-20 minute overview of AppCloud