From Java...to Rails


             Nick Sieger
             @nicksieger
Are you happy with
your development pace


        ?
?
How do you get to a place
   where it’s better?
Introduce
Language
Replace JSF with
  *Anything*
throw away
Built environment
    long-running projects
    with legacy codebases
Sagrada Família,
Barcelona, Spain
passion
                     facade


   nativity
   facade


scaffolded interior
Ryugyong Hotel,
2004     North Korea     2011
seismic retrofit
Szkieletor,
Kraków, Poland
Metaphor    Use Ruby, JRuby, and Rails to...

 Sagrada    • Build new facade faster
 Familia    • Scaffolding during refactoring

Ryugyong
         • Revive a project with a new face
  Hotel

 Seismic    • Reinforce business rules with a DSL
 retrofit    • Harden security


Szkieletor • Find novel uses for abandoned code
Metaphor    Use Ruby, JRuby, and Rails to...

 Sagrada    • Build new facade faster
 Familia    • Scaffolding during refactoring

Ryugyong
         • Revive a project with a new face
  Hotel

 Seismic    • Reinforce business rules with a DSL
 retrofit    • Harden security


Szkieletor • Find novel uses for abandoned code
Metaphor    Use Ruby, JRuby, and Rails to...

 Sagrada    • Build new facade faster
 Familia    • Scaffolding during refactoring

Ryugyong
         • Revive a project with a new face
  Hotel

 Seismic    • Reinforce business rules with a DSL
 retrofit    • Harden security


Szkieletor • Find novel uses for abandoned code
Metaphor    Use Ruby, JRuby, and Rails to...

 Sagrada    • Build new facade faster
 Familia    • Scaffolding during refactoring

Ryugyong
         • Revive a project with a new face
  Hotel

 Seismic    • Reinforce business rules with a DSL
 retrofit    • Harden security


Szkieletor • Find novel uses for abandoned code
Metaphor    Use Ruby, JRuby, and Rails to...

 Sagrada    • Build new facade faster
 Familia    • Scaffolding during refactoring

Ryugyong
         • Revive a project with a new face
  Hotel

 Seismic    • Reinforce business rules with a DSL
 retrofit    • Harden security


Szkieletor • Find novel uses for abandoned code
Biological evolution
    new replaces old over time
Strangler Fig
github.com/nicksieger/refactoring-to-rails
Before we begin...
Test Plan
Don’t leave home without it
gembundler.com
Bundler

source :rubygems

group   :test do
  gem   'rspec-rails'
  gem   'cucumber-rails'
  gem   'capybara'
end
Feature: Owners

  Scenario: Add New Owner
    Given I am on the new owner page
    When I fill in the following:
      | First name | Dan          |
      | Last name | Wood          |
      | Address    | 123 Main St |
      | City       | Anywhere     |
      | Telephone | 5555555       |
    And I press "Add Owner"
    Then I should see "Owner Information" within "h2"
    And I should see "Dan Wood"
Foot in the door
    Sneaking Ruby in
JRuby-Rack
org.jruby.rack:jruby-rack
Servlet
Java          Ruby




 /*          /rack/*


       App
<listener>
  <listener-class>
    org.jruby.rack.RackServletContextListener
  </listener-class>
</listener>

<servlet>
  <servlet-name>rack</servlet-name>
  <servlet-class>org.jruby.rack.RackServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>rack</servlet-name>
  <url-pattern>/rack/*</url-pattern>
</servlet-mapping>
# WEB-INF/config.ru
require 'sinatra'

if development?
  require 'sinatra/reloader'
  use Rack::ShowExceptions
end

require 'app'

set :run, false
run Sinatra::Application
# app.rb
get '/rack/' do
  '<h1>Sinatra</h1>'
end
REST
Not just APIs...
URIs + HREFs
 Architecture of the Web
<a href="/vets.xml">View as XML</a>
<a href="/rack/vets.xml">View as XML</a>
In JSPs

<jruby-rack:rails path="/rack/vets" params="layout=none"/>
Red Green Refactor
    Continuous improvement
Interceptor pattern
     Partial strangulation
Filter




                        /owners    Java/
/   /vets     /owners    /1/pets   Spring

            App
Filter



/   /vets                          Ruby

                        /owners    Java/
/   /vets     /owners    /1/pets   Spring

            App
SpringPetclinic::Application.routes.draw do

  root :to => "welcome#index"

  resources :vets

end
Rails      Java
Request
          response   response


   /      200 OK      (N/A)


          404 Not
/owners              200 OK
           Found
Re-use views
   JSP-in-ERB
<%= request.render '/WEB-INF/jsp/header.jsp' %>

<%= yield %>

<%= request.render '/WEB-INF/jsp/footer.jsp' %>
Re-use models
  Hibernate + ActiveModel
# app/models/owner.rb
java_import org.springframework.samples.petclinic.Owner
# app/models/owner.rb
java_import org.springframework.samples.petclinic.Owner

class Owner
  extend ActiveModel::Naming
  include ActiveModel::Validations
  include ActiveModel::Conversion




end
# app/models/owner.rb
java_import org.springframework.samples.petclinic.Owner

class Owner
  extend ActiveModel::Naming
  include ActiveModel::Validations
  include ActiveModel::Conversion

  validates_presence_of :first_name, :last_name,
    :address, :city, :telephone
  validates_format_of :telephone, :with => /[-0-9.+ ]+/,
    :message => "..."
end
<%# app/views/owner/_form.html.erb %>
<%= form_for @owner do |f| %>

   <%= f.label :first_name %>
   <br/>
   <%= f.text_field :first_name %>

   <%= f.label :last_name %>
   <br/>
   <%= f.text_field :last_name %>

   <%# ... %>
<% end -%>
<%# app/views/owner/_form.html.erb %>
<%= form_for @owner do |f| %>
            @owner
   <%= f.label :first_name %>
   <br/>
   <%= f.text_field :first_name %>

   <%= f.label :last_name %>
   <br/>
   <%= f.text_field :last_name %>

   <%# ... %>
<% end -%>
Rails takes over
    Final strangulation
$ rails new petclinic --skip-active-record
$ mvn org.jruby.plugins:jruby-rake-plugin:classpath
# config/initializers/classpath.rb
module Maven
  extend self

  CLASSPATH = [
    "#{BASEDIR}/target/classes",
    "#{ENV['HOME']}/.m2/.../org.springframework.core-3.0.0.RELEASE.jar",
    # lots of jars here...
  ]

  def set_classpath
    require 'java'
    CLASSPATH.each {|p| $CLASSPATH << p }
  end
end
Maven.set_classpath

module Spring
  SPRING_XML_CONFIG_FILES = [
    'classpath:applicationContext.xml'
  ].to_java :string      # creates a String[]

  CONTEXT = ClassPathXmlApplicationContext.new(
    SPRING_XML_CONFIG_FILES)
end
Warbler
INSTALL   gem install warbler
# config/warble.rb
Warbler::Config.new do |config|

  require 'config/initializers/classpath'
  config.java_libs += Maven.jar_files

  config.java_classes = FileList["target/classes/**/*"]

end
$ warble executable war
Creating refactoring-to-rails.war
$ java -jar refactoring-to-rails.war
Hollow out the tree
JRuby T-Shirts!
Stop by booth #5605
Party Tue 6:30pm
http://ey.io/oeuot1
➡ Script Bowl
     Nic Williams
     Wed 8:30 AM–Hilton Grand Ballroom B

➡ Accelerate Your Business and Aim for the
  Cloud with Java and JRuby
     Jacob Lehrbaum, Mike Piech
     Wed 3:00 PM–Parc 55 Embarcadero

➡ Real World JRuby
     Charles Nutter, Thomas Enebo
     Wed 4:30 PM–Parc 55 Market Street
Images
http://www.flickr.com/photos/john_mcclumpha/4138419594/
http://www.flickr.com/photos/phil_shirley/4500893932/
http://www.flickr.com/photos/y_i/2330044065/
http://www.flickr.com/photos/herzogbr/462383777/
http://en.wikipedia.org/wiki/File:Sagrada_Familia_01.jpg
http://www.flickr.com/photos/koocheekoo/38407225/
http://www.flickr.com/photos/27649557@N07/5000528445/
http://www.flickr.com/photos/gpaumier/446059442/
http://www.flickr.com/photos/ilm/12831049/
http://upload.wikimedia.org/wikipedia/commons/9/95/Ryugyong_hotel_01.jpg
http://upload.wikimedia.org/wikipedia/commons/7/78/
Ryugyeong_Hotel_on_February_2011.jpg
http://en.wikipedia.org/wiki/File:ExteiorShearTruss.jpg
http://en.wikipedia.org/wiki/File:ExtReenfDetail.jpg
http://en.wikipedia.org/wiki/File:Szkieleteor_in_krakow.JPG
http://www.flickr.com/photos/epingchris/5110376533/
http://www.flickr.com/photos/bazylek/3194294047/
http://www.flickr.com/photos/58847482@N03/5920653295/
http://www.flickr.com/photos/nancybaym/3828905896/
http://www.flickr.com/photos/anitagould/5501316782/

From java to rails