JRuby and You
                                Hiro Asari
                                Engine Yard




Wednesday, October 26, 11
History
                      September 10, 2001




                            Source: Wikipedia



Wednesday, October 26, 11
Wednesday, October 26, 11
Project Status


                    • Current stable release: 1.6.5 (Oct 25, 2011)
                    • Rails 3.1-compatible


Wednesday, October 26, 11
What’s next in 1.7?


                    • JSR 292 (a.k.a. invokedynamic) support
                    • Improved Ruby 1.9 support


Wednesday, October 26, 11
What’s in it for Java
                             programmers?

                    • REPL
                    • Testing frameworks
                    • Fun


Wednesday, October 26, 11
What’s in it for
                             Rubyists?
                    • Real threads
                    • No more GIL
                    • Mature garbage collector
                    • Easy deployment

Wednesday, October 26, 11
Try JRuby
                            http://jruby.org/tryjruby




Wednesday, October 26, 11
Getting JRuby

        wget http://bit.ly/jruby_bin_165 | 
        tar xzvf -

        export PATH=$PATH:$PWD/jruby-1.6.5/bin




Wednesday, October 26, 11
jruby -S irb
Wednesday, October 26, 11
Java Integration

                              require 'java'




Wednesday, October 26, 11
Loading JAR

                            require 'example.jar'




Wednesday, October 26, 11
Importing Java Class

      StringBuffer = java.lang.StringBuffer
      sb = StringBuffer.new "foo"




Wednesday, October 26, 11
java_import

        java_import java.lang.StringBuffer
        java_import 'java.lang.StringBuffer'




Wednesday, October 26, 11
Static methods

        java.lang.System.currentTimeMillis
        java.lang.System.current_time_millis




Wednesday, October 26, 11
Static Fields

        java_import java.util.logging.Logger
        java_import java.util.loggin.Level

        Logger.global.log Level::SEVERE, "…"




Wednesday, October 26, 11
Constructor

      URL.new 'http://engineyard.com'
      URL.new 'http', 'engineyard.com', '/'




Wednesday, October 26, 11
Instance methods
                            #given
                            # void setPrice(int):
                            car.setPrice(2000)
                            car.price = 2000

                            # int getPrice()
                            car.price




Wednesday, October 26, 11
Explicit Coercion

                             measurement = 5
                             measurement.to_java




Wednesday, October 26, 11
Overloaded methods
       public class C {
         public static String method(String s) {
           return "String";
         }
         public static String method(long l) {
           return "long";
         }
       }




Wednesday, October 26, 11
Overloaded methods


      obj = C.new
      obj.method("foo") # => "String"
      obj.method(5) # => "long"




Wednesday, October 26, 11
Overloaded methods
                public class C {
                  public String method(int i) {
                    return "int";
                  }
                  public String method(long l) {
                    return "long";
                  }
                }


Wednesday, October 26, 11
Overloaded methods

      obj = C.new
      obj.method(5) # => "long"
      obj.method(5.to_java(Java::int))
      obj.java_send :method, [Java::int], 5




Wednesday, October 26, 11
Java Interfaces

      callable =
      java.util.concurrent.Executors.callable do
        puts "foo"
      end

      callable.call




Wednesday, October 26, 11
Complex Example with
                        Akka
                       Java source: http://bit.ly/lTClmr
                       Ruby source: https://gist.github.com/1013227
                       http://www.engineyard.com/blog/2011/using-
                       java-from-ruby-with-jruby-irb/




Wednesday, October 26, 11
GUI

               Redcar

 http://redcareditor.com/




Wednesday, October 26, 11
Grafting Rails into
                              Spring MVC




Wednesday, October 26, 11
Pet Clinic

                                    • Example
                                         database-
                                         backed web
                                         app for
                                         Spring
                                         framework


Wednesday, October 26, 11
Requests


                                                 JRuby

                            /   /vets   /rack/   Java/
                                                 Spring

                                App
Wednesday, October 26, 11
Adding Route
   diff --git a/src/main/webapp/WEB-INF/jsp/vets.jsp b/src/main/webapp/WEB-INF/jsp/vets.jsp
   index cff2154..0d99817 100644
   --- a/src/main/webapp/WEB-INF/jsp/vets.jsp
   +++ b/src/main/webapp/WEB-INF/jsp/vets.jsp
   @@ -23,7 +23,7 @@
     <table class="table-buttons">
       <tr>
         <td>
   -        <a href="<spring:url value="/vets.xml" htmlEscape="true" />">View as XML</a>
   +        <a href="<spring:url value="/rack/vets.xml" htmlEscape="true" />">View as XML</a>
         </td>
       </tr>
     </table>




Wednesday, October 26, 11
Cucumber


                    • http://cukes.info
                    • Testing framework for describing software
                            behavior in plain English




Wednesday, October 26, 11
Cucumber
         Feature: Pets

                Scenario: Edit Pet
                  Given I am on the owners search page
                  And I press "Find Owners"
                  And I follow "George Franklin"
                  And I follow "Edit Pet"
                  When I fill in "Name" with "Leoni"
                  And press "Update Pet"
                  Then I should see "Leoni"



Wednesday, October 26, 11
Cucumber test
          Stand by while Tomcat finishes booting...
          Using the default profile...
          ............................................................F-.............

          (::) failed steps (::)

          expected: /xml/,
                got: "text/html;charset=utf-8" (using =~)
          Diff:
          @@ -1,2 +1,2 @@
          -/xml/
          +text/html;charset=utf-8
           (RSpec::Expectations::ExpectationNotMetError)
          org/jruby/RubyProc.java:268:in `call'
          ./features/step_definitions/xml_json_steps.rb:12:in `(root)':in `/^I should see
          an XML document$/'
          features/vets.feature:6:in `Then I should see an XML document'

          Failing Scenarios:
          cucumber features/vets.feature:3 # Scenario: View vets as XML

          13 scenarios (1 failed, 12 passed)
          75 steps (1 failed, 1 skipped, 73 passed)
          0m7.709s
          rake aborted!
          Cucumber failed



Wednesday, October 26, 11
diff --git a/pom.xml b/pom.xml
                            index 9e22f83..0810701 100644
                            --- a/pom.xml
                            +++ b/pom.xml
                            @@ -211,6 +211,18 @@
                                                    <scope>provided</scope>
                                            </dependency>

                            +                <!-- JRuby and JRuby-Rack -->
                            +                <dependency>
                            +                        <groupId>org.jruby</groupId>
                            +                        <artifactId>jruby-complete</artifactId>
                            +                        <version>1.6.0</version>
                            +                </dependency>
                            +                <dependency>
                            +                        <groupId>org.jruby.rack</groupId>
                            +                        <artifactId>jruby-rack</artifactId>
                            +                        <version>1.0.8</version>
                            +                </dependency>
                            +
                                            <!-- Test dependencies -->
                                            <dependency>
                                                    <groupId>org.junit</groupId>




Wednesday, October 26, 11
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
    index 8d02684..60ed6cb 100644
    --- a/src/main/webapp/WEB-INF/web.xml
    +++ b/src/main/webapp/WEB-INF/web.xml
    @@ -87,6 +87,21 @@
            <listener>
                    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
            </listener>
    +
    +        <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>
    +

                <!--
                            Defines the 'default' servlet (usually for service static resources).




Wednesday, October 26, 11
diff --git a/src/main/webapp/WEB-INF/lib/app.rb b/src/main/webapp/WEB-INF/lib/
                     app.rb
                     index 6ab5b3c..4398fb4 100644
                     --- a/src/main/webapp/WEB-INF/lib/app.rb
                     +++ b/src/main/webapp/WEB-INF/lib/app.rb
                     @@ -1,6 +1,33 @@
                       require 'builder'
                       require 'erb'
                     +require 'spring_helpers'
                     +
                     +helpers do
                     + include Spring
                     +end

                      get '/rack/' do
                        '<h1>Sinatra</h1>'
                      end
                     +
                     +get '/rack/vets.xml' do
                     + content_type 'application/vnd.petclinic+xml'
                     + builder do |xml|
                     +    xml.instruct!
                     +    xml.vets do
                     +      clinic.vets.each do |vet|
                     +        xml.vetList do
                     +          xml.id vet.id
                     +          xml.firstName vet.firstName
                     +          xml.lastName vet.lastName
                     +          vet.specialties.each do |spec|
                     +            xml.specialties do
                     +              xml.id spec.id
                     +              xml.name spec.name
                     +            end
                     +          end
                     +        end
                     +      end
                     +    end
                     + end
                     +end


Wednesday, October 26, 11
Requests



                      /     /vets                        JRuby

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


                               App
Wednesday, October 26, 11
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
               index 60ed6cb..f64b34d 100644
               --- a/src/main/webapp/WEB-INF/web.xml
               +++ b/src/main/webapp/WEB-INF/web.xml
               @@ -92,16 +92,6 @@
                                <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>
               -

                            <!--
                               Defines the 'default' servlet (usually for service static resources).
               @@ -162,6 +152,16 @@
                               <url-pattern>/</url-pattern>
                       </servlet-mapping>

               +             <filter>
               +                     <filter-name>RackFilter</filter-name>
               +                     <filter-class>org.jruby.rack.RubyFirstRackFilter</filter-class>
               +             </filter>
               +
               +             <filter-mapping>
               +                     <filter-name>RackFilter</filter-name>
               +                     <url-pattern>/*</url-pattern>
               +             </filter-mapping>
               +
                            <filter>
                                       <filter-name>httpMethodFilter</filter-name>
                                       <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>




Wednesday, October 26, 11
The Book

                      http://pragprog.com/book/
                      jruby/using-jruby

                      25% off for one week
                      only: http://bit.ly/vd4Mhj




Wednesday, October 26, 11
Engine Yard

                        500 free hours
                     http://engineyard.com




Wednesday, October 26, 11
Questions?
                        Twitter @hiro_asari
                     G+ http://gplus.to/hiroasari
               LinkedIn http://linkedin.com/in/hiroasari

                             asari.ruby@gmail.com
                            hasari@engineyard.com

                        http://github.com/banzaiman


                                                           http://www.flickr.com/photos/42033648@N00/372887164



Wednesday, October 26, 11

JRuby and You

  • 1.
    JRuby and You Hiro Asari Engine Yard Wednesday, October 26, 11
  • 2.
    History September 10, 2001 Source: Wikipedia Wednesday, October 26, 11
  • 3.
  • 4.
    Project Status • Current stable release: 1.6.5 (Oct 25, 2011) • Rails 3.1-compatible Wednesday, October 26, 11
  • 5.
    What’s next in1.7? • JSR 292 (a.k.a. invokedynamic) support • Improved Ruby 1.9 support Wednesday, October 26, 11
  • 6.
    What’s in itfor Java programmers? • REPL • Testing frameworks • Fun Wednesday, October 26, 11
  • 7.
    What’s in itfor Rubyists? • Real threads • No more GIL • Mature garbage collector • Easy deployment Wednesday, October 26, 11
  • 8.
    Try JRuby http://jruby.org/tryjruby Wednesday, October 26, 11
  • 9.
    Getting JRuby wget http://bit.ly/jruby_bin_165 | tar xzvf - export PATH=$PATH:$PWD/jruby-1.6.5/bin Wednesday, October 26, 11
  • 10.
  • 11.
    Java Integration require 'java' Wednesday, October 26, 11
  • 12.
    Loading JAR require 'example.jar' Wednesday, October 26, 11
  • 13.
    Importing Java Class StringBuffer = java.lang.StringBuffer sb = StringBuffer.new "foo" Wednesday, October 26, 11
  • 14.
    java_import java_import java.lang.StringBuffer java_import 'java.lang.StringBuffer' Wednesday, October 26, 11
  • 15.
    Static methods java.lang.System.currentTimeMillis java.lang.System.current_time_millis Wednesday, October 26, 11
  • 16.
    Static Fields java_import java.util.logging.Logger java_import java.util.loggin.Level Logger.global.log Level::SEVERE, "…" Wednesday, October 26, 11
  • 17.
    Constructor URL.new 'http://engineyard.com' URL.new 'http', 'engineyard.com', '/' Wednesday, October 26, 11
  • 18.
    Instance methods #given # void setPrice(int): car.setPrice(2000) car.price = 2000 # int getPrice() car.price Wednesday, October 26, 11
  • 19.
    Explicit Coercion measurement = 5 measurement.to_java Wednesday, October 26, 11
  • 20.
    Overloaded methods public class C { public static String method(String s) { return "String"; } public static String method(long l) { return "long"; } } Wednesday, October 26, 11
  • 21.
    Overloaded methods obj = C.new obj.method("foo") # => "String" obj.method(5) # => "long" Wednesday, October 26, 11
  • 22.
    Overloaded methods public class C { public String method(int i) { return "int"; } public String method(long l) { return "long"; } } Wednesday, October 26, 11
  • 23.
    Overloaded methods obj = C.new obj.method(5) # => "long" obj.method(5.to_java(Java::int)) obj.java_send :method, [Java::int], 5 Wednesday, October 26, 11
  • 24.
    Java Interfaces callable = java.util.concurrent.Executors.callable do puts "foo" end callable.call Wednesday, October 26, 11
  • 25.
    Complex Example with Akka Java source: http://bit.ly/lTClmr Ruby source: https://gist.github.com/1013227 http://www.engineyard.com/blog/2011/using- java-from-ruby-with-jruby-irb/ Wednesday, October 26, 11
  • 26.
    GUI Redcar http://redcareditor.com/ Wednesday, October 26, 11
  • 27.
    Grafting Rails into Spring MVC Wednesday, October 26, 11
  • 28.
    Pet Clinic • Example database- backed web app for Spring framework Wednesday, October 26, 11
  • 29.
    Requests JRuby / /vets /rack/ Java/ Spring App Wednesday, October 26, 11
  • 30.
    Adding Route diff --git a/src/main/webapp/WEB-INF/jsp/vets.jsp b/src/main/webapp/WEB-INF/jsp/vets.jsp index cff2154..0d99817 100644 --- a/src/main/webapp/WEB-INF/jsp/vets.jsp +++ b/src/main/webapp/WEB-INF/jsp/vets.jsp @@ -23,7 +23,7 @@ <table class="table-buttons"> <tr> <td> - <a href="<spring:url value="/vets.xml" htmlEscape="true" />">View as XML</a> + <a href="<spring:url value="/rack/vets.xml" htmlEscape="true" />">View as XML</a> </td> </tr> </table> Wednesday, October 26, 11
  • 31.
    Cucumber • http://cukes.info • Testing framework for describing software behavior in plain English Wednesday, October 26, 11
  • 32.
    Cucumber Feature: Pets Scenario: Edit Pet Given I am on the owners search page And I press "Find Owners" And I follow "George Franklin" And I follow "Edit Pet" When I fill in "Name" with "Leoni" And press "Update Pet" Then I should see "Leoni" Wednesday, October 26, 11
  • 33.
    Cucumber test Stand by while Tomcat finishes booting... Using the default profile... ............................................................F-............. (::) failed steps (::) expected: /xml/, got: "text/html;charset=utf-8" (using =~) Diff: @@ -1,2 +1,2 @@ -/xml/ +text/html;charset=utf-8 (RSpec::Expectations::ExpectationNotMetError) org/jruby/RubyProc.java:268:in `call' ./features/step_definitions/xml_json_steps.rb:12:in `(root)':in `/^I should see an XML document$/' features/vets.feature:6:in `Then I should see an XML document' Failing Scenarios: cucumber features/vets.feature:3 # Scenario: View vets as XML 13 scenarios (1 failed, 12 passed) 75 steps (1 failed, 1 skipped, 73 passed) 0m7.709s rake aborted! Cucumber failed Wednesday, October 26, 11
  • 34.
    diff --git a/pom.xmlb/pom.xml index 9e22f83..0810701 100644 --- a/pom.xml +++ b/pom.xml @@ -211,6 +211,18 @@ <scope>provided</scope> </dependency> + <!-- JRuby and JRuby-Rack --> + <dependency> + <groupId>org.jruby</groupId> + <artifactId>jruby-complete</artifactId> + <version>1.6.0</version> + </dependency> + <dependency> + <groupId>org.jruby.rack</groupId> + <artifactId>jruby-rack</artifactId> + <version>1.0.8</version> + </dependency> + <!-- Test dependencies --> <dependency> <groupId>org.junit</groupId> Wednesday, October 26, 11
  • 35.
    diff --git a/src/main/webapp/WEB-INF/web.xmlb/src/main/webapp/WEB-INF/web.xml index 8d02684..60ed6cb 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -87,6 +87,21 @@ <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> + + <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> + <!-- Defines the 'default' servlet (usually for service static resources). Wednesday, October 26, 11
  • 36.
    diff --git a/src/main/webapp/WEB-INF/lib/app.rbb/src/main/webapp/WEB-INF/lib/ app.rb index 6ab5b3c..4398fb4 100644 --- a/src/main/webapp/WEB-INF/lib/app.rb +++ b/src/main/webapp/WEB-INF/lib/app.rb @@ -1,6 +1,33 @@ require 'builder' require 'erb' +require 'spring_helpers' + +helpers do + include Spring +end get '/rack/' do '<h1>Sinatra</h1>' end + +get '/rack/vets.xml' do + content_type 'application/vnd.petclinic+xml' + builder do |xml| + xml.instruct! + xml.vets do + clinic.vets.each do |vet| + xml.vetList do + xml.id vet.id + xml.firstName vet.firstName + xml.lastName vet.lastName + vet.specialties.each do |spec| + xml.specialties do + xml.id spec.id + xml.name spec.name + end + end + end + end + end + end +end Wednesday, October 26, 11
  • 37.
    Requests / /vets JRuby /owners Java/ / /vets /owners /1/pets Spring App Wednesday, October 26, 11
  • 38.
    diff --git a/src/main/webapp/WEB-INF/web.xmlb/src/main/webapp/WEB-INF/web.xml index 60ed6cb..f64b34d 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -92,16 +92,6 @@ <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> - <!-- Defines the 'default' servlet (usually for service static resources). @@ -162,6 +152,16 @@ <url-pattern>/</url-pattern> </servlet-mapping> + <filter> + <filter-name>RackFilter</filter-name> + <filter-class>org.jruby.rack.RubyFirstRackFilter</filter-class> + </filter> + + <filter-mapping> + <filter-name>RackFilter</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + <filter> <filter-name>httpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> Wednesday, October 26, 11
  • 39.
    The Book http://pragprog.com/book/ jruby/using-jruby 25% off for one week only: http://bit.ly/vd4Mhj Wednesday, October 26, 11
  • 40.
    Engine Yard 500 free hours http://engineyard.com Wednesday, October 26, 11
  • 41.
    Questions? Twitter @hiro_asari G+ http://gplus.to/hiroasari LinkedIn http://linkedin.com/in/hiroasari asari.ruby@gmail.com hasari@engineyard.com http://github.com/banzaiman http://www.flickr.com/photos/42033648@N00/372887164 Wednesday, October 26, 11