Your SlideShare is downloading. ×
0
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
JRuby 6 Years in Production
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

JRuby 6 Years in Production

974

Published on

Insight from using JRuby in production for six years integrating with Java services, such as Spring.

Insight from using JRuby in production for six years integrating with Java services, such as Spring.

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
974
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. JRuby Insights from Six Years in Production Mark Menard Enable Labs
  • 2. How do you get Ruby into a Java shop? How do you move past Java to Ruby? How do you get Ruby into a legacy Java app? Enable Labs !2 @mark_menard
  • 3. Who are you? Enable Labs !3 @mark_menard
  • 4. You love Ruby! Enable Labs !4 @mark_menard
  • 5. You work in a Java shop. Enable Labs !5 @mark_menard
  • 6. You have a client who uses Java. Enable Labs !6 @mark_menard
  • 7. You have to work on something that uses Java. Enable Labs !7 @mark_menard
  • 8. You have a project that could benefit from true concurrency. Enable Labs !8 @mark_menard
  • 9. Why? Enable Labs !9 @mark_menard
  • 10. So... what is JRuby anyway? Enable Labs !10 @mark_menard
  • 11. But I use MRI! What’s different? Enable Labs !11 @mark_menard
  • 12. To Summarize • • • • • • Enable Labs A JVM is required. Start up is a little slower. Prefer pure Ruby gems, or gems that have JRuby versions. Try to avoid gems with C-extensions. No continuations. No fork() Regular expressions use 1.9 semantics even in 1.8 mode. • !12 @mark_menard
  • 13. What can JRuby do for you? Enable Labs !13 @mark_menard
  • 14. Parallelism in JRuby Enable Labs !14 @mark_menard
  • 15. my_thread = Thread.new do (1..100_000).each { |i| i * 2 } end ! # Do some more work. ! my_thread.join # Wait for my_thread to finish. Enable Labs !15 @mark_menard
  • 16. require 'peach' require 'benchmark' ! overall_results = Benchmark.measure do (1..100_000).peach(8) do |i| 1000.times do |n| a, b = 0, 1 a, b = b, a+b end end end puts overall_results Enable Labs !16 @mark_menard
  • 17. $ rvm use 2.0 Using /Users/mark/.rvm/gems/ruby-2.0.0-p247 $ ruby peach_example.rb 41.250000 0.060000 41.310000 ( 41.302095) $ rvm use jruby Using /Users/mark/.rvm/gems/jruby-1.7.5 $ ruby peach_example.rb 9.960000 0.170000 10.130000 ( 1.437000) Enable Labs !17 @mark_menard
  • 18. Using Java Libraries Enable Labs !18 @mark_menard
  • 19. require 'java' require "#{File.expand_path(File.dirname(__FILE__))}/itextpdf-5.4.4.jar" ! # Make Java classes top level constants. java_import com.itextpdf.text.Document Document.__persistent__ = true java_import com.itextpdf.text.pdf.PdfWriter java_import java.io.FileOutputStream java_import com.itextpdf.text.Paragraph document = Document.new pdfWriter = PdfWriter.get_instance(document, FileOutputStream.new("document.pdf")) document.open document.add(Paragraph.new("Hello JRuby")) document.close Enable Labs !19 @mark_menard
  • 20. require 'itext' Itext::Document.create("document.pdf") do p "Hello from JRuby" end Enable Labs !20 @mark_menard
  • 21. require 'java' require "#{File.expand_path(File.dirname(__FILE__))}/itextpdf-5.4.4.jar" ! module Itext # Namespace the Java classes for convenience. java_import com.itextpdf.text.Document Document.__persistent__ = true java_import com.itextpdf.text.pdf.PdfWriter java_import java.io.FileOutputStream java_import com.itextpdf.text.Paragraph end Enable Labs !21 @mark_menard
  • 22. module Itext # Re-open the *Java* Document class. class Document def self.create (filename, &block) document = self.new pdf_writer = PdfWriter.get_instance(document, FileOutputStream.new(filename)) document.open document.instance_eval(&block) document.close end ! def paragraph (content) add(Paragraph.new(content)) end alias_method :p, :paragraph end end Enable Labs !22 @mark_menard
  • 23. require 'itext' Itext::Document.create("document.pdf") do p "Hello from JRuby" end Enable Labs !23 @mark_menard
  • 24. require 'java' ! frame = javax.swing.JFrame.new frame.set_default_close_operation javax.swing.JFrame::EXIT_ON_CLOSE frame.set_size(300, 200) frame.get_content_pane.add javax.swing.JLabel.new('Hello world!') frame.set_visible true Enable Labs !24 @mark_menard
  • 25. Case Studies Enable Labs !25 @mark_menard
  • 26. Case Study 1 ! What the Client Wanted ! 1Q2008 Enable Labs • New functionality that was predominantly orthogonal to their existing app. • Single Signon • Faster Development Times • Some integration at the data level. !26 @mark_menard
  • 27. • Struts 2 • Groovy 1.0 • Jetty Running Un-war'ed • Spring Dependency Injection XML Hell • Struts 2 - More XML Hell Case Study 1 ! The Technical Environment ! • Mostly Continuous Deployment Enable Labs !27 @mark_menard
  • 28. Case Study 1 ! What We Used • JRuby 1.0 • Rails 2.1 • ERB Enable Labs !28 @mark_menard
  • 29. Case Study 1 ! What Made it Work Java Integration Enable Labs !29 @mark_menard
  • 30. Case Study 1 ! The Challenges Enable Labs • Integrating the Signin Process • Accessing the Spring Context • Reusing Existing Permission System • Deployment • Gem Management !30 @mark_menard
  • 31. • Initiate all signins on the Rails side of the application. • On success setup the HTTP session for both the Java and Rails sides of the app. • Also handle signout in Rails. Enable Labs !31 Case Study 1 ! Integrating the Signin Process @mark_menard
  • 32. • Create a Java object that holds a Case Study 1 ! Accessing the Spring Context Enable Labs static reference to the Spring context, the SpringApplicationContextFinder. • The finder is initialized at startup with the reference to the context. • Make a Ruby DSL to access Spring. !32 @mark_menard
  • 33. public class SpringApplicationContextFinder implements ApplicationContextAware { ! ! ! } private static ApplicationContext CONTEXT; /** * This method is called from within the ApplicationContext once it is * done starting up, it will stick a reference to itself into this bean. * @param context a reference to the ApplicationContext. */ public void setApplicationContext(ApplicationContext context) throws BeansException { CONTEXT = context; } /** * Return a reference to the Spring application context. * @return SpringApplicationContext */ public static Object getContext () { return CONTEXT; } Enable Labs !33 @mark_menard
  • 34. module SpringSupport def get_spring_context @context ||= Java::lib.SpringApplicationContextFinder.getContext() end end Enable Labs !34 @mark_menard
  • 35. class SomeObject include SpringSupport ! spring_dependency :some_spring_service ! def do_something (arg) ! #@some_spring_service <---- This is a Java object. ! some_spring_service.do_something(arg) end end ! result = SomeObject.new.do_something("abc") Enable Labs !35 @mark_menard
  • 36. • Permission system written in Case Study 1 ! Reusing Existing Permission System Enable Labs Java/Groovy. • Still needed to be accessible from Java/Groovy. • Did not want to maintain two versions of the permission system. !36 @mark_menard
  • 37. • Use the Spring implementation Case Study 1 ! Reusing Existing Permission System of permissions. • Check permissions in a before_filter. • Use the SpringSupport to get access to the security manager. ! Solution Enable Labs !37 @mark_menard
  • 38. class CheckSecurityAccessService < Struct.new(:url, :user) include SpringSupport spring_dependency :security_manager ! def execute security_manager.check_security_access(build_vr_context) end alias_method :succeeded?, :execute ! private ! def build_vr_context VRContext.new(HashMap.new('url' => url, 'user' => user)) end ! end Enable Labs !38 @mark_menard
  • 39. Case Study 1 ! Deployment and Gem Management Enable Labs • App used Jetty un-war’ed. • Warbler didn’t apply. • Layout Rails app in /WEB-INF • Used GoldSpike servlet to front Rails. (We have since updated to jruby-rack and a Servlet filter.) • Vendor EVERYTHING and check it into git. !39 @mark_menard
  • 40. • Completed work in about 3 Case Study 1 ! Success Enable Labs months. • Much better test coverage. • This module is still orthogonal to the main app today. • Code has been very stable. • Code has been ported through multiple versions of Rails. • Almost all new functionality is done in Rails since 1Q2008. !40 @mark_menard
  • 41. • Minimal integration with existing application. • Highly compartmentalized. • Focused feature set with stable requirements. • Java integration worked. Case Study 1 ! Why did it succeed? Enable Labs !41 @mark_menard
  • 42. Case Study 2 And Steve said, “let there be iPhone.” Enable Labs !42 @mark_menard
  • 43. • Client wants about 10 screens available in the browser on the iPhone. • He has a trip in two weeks and wants it working before he leaves. Case Study 2 ! iPhone Enable Labs !43 @mark_menard
  • 44. • Working screens inside of a week. • Ready for his trip in two weeks. • Went on to be used by the field sales staff for several years. • Total cost far below the client’s expectation. Case Study 2 Rails to the Rescue ! ! iPhone A rip roaring success Enable Labs !44 @mark_menard
  • 45. Case Study 3 ! Porting to Ruby First Attempt ! A Study in Over Enthusiasm This JRuby is Awesome! Let’s Port the App! Enable Labs !45 @mark_menard
  • 46. Let’s talk about the brownfield. • 388 Views • 272 Struts 2 Actions • 30 Spring Service Beans • 81 Data Access Objects • 151 Hibernate/JPA Entities (Models) • Not Enough Tests • Primary implementation language is Groovy Enable Labs Case Study 3 ! Porting to Ruby First Attempt !46 @mark_menard
  • 47. Case Study 3 Current Architecture Enable Labs !47 @mark_menard
  • 48. • Ruby classes can implement Java interfaces. Case Study 3 ! Porting to Ruby First Attempt Enable Labs !48 @mark_menard
  • 49. public interface Person { public String getName (); public void setName (String name); } class Person include Java::Person ! attr_accessor :name end Enable Labs !49 @mark_menard
  • 50. • Ruby classes can implement Java interfaces. • Plug a Ruby/Rails environment into Spring to manufacture Ruby “beans”. Case Study 3 ! Porting to Ruby First Attempt Enable Labs !50 @mark_menard
  • 51. def getInventoryManager () { log.debug "[ RailsFactory.groovy ] : Instantiating Integration::InventoryManager" eval "Integration::InventoryManager.newn" } Enable Labs !51 @mark_menard
  • 52. • Ruby classes can implement Java Case Study 3 ! Porting to Ruby First Attempt Enable Labs interfaces. • Plug a Ruby/Rails environment into Spring to manufacture Ruby “beans”. • On a case-by-case basis port Java/Groovy Spring service beans to JRuby. • This was a bottom up port. !52 @mark_menard
  • 53. Rationale Case Study 3 ! Porting to Ruby First Attempt Enable Labs • No need to mess with the user experience. The views and controllers won’t change. • Can do it incrementally. • Allows Java, Groovy and JRuby objects to just inter-play. • Should be transparent. !53 @mark_menard
  • 54. Outcome • Technical success, business failure. • Did not take full advantage of our Ruby tools. • There was no driving business value in doing it. Case Study 3 ! Porting to Ruby First Attempt Enable Labs !54 @mark_menard
  • 55. Case Study 4 ! Porting to Rails Part 2 Ah.... sweet incremental success... ...mostly. Enable Labs !55 @mark_menard
  • 56. • Do all new work in JRuby. • Find silos of existing functionality. • Wait for significant changes in requirements for the silo. • Port one silo at a time. • Port the whole silo to JRuby. • Write lots of tests. • Find improvements to UI/UX that can be rolled in for justification. • Use SOA for non-user facing services. Enable Labs !56 Case Study 4 ! Porting to Rails Part 2 @mark_menard
  • 57. Case Study 4 ! Porting to Rails Part 2 The God Object in the Closet Enable Labs !57 @mark_menard
  • 58. The God Object in the Closet The Strategy ! Make the God object a web service. Implement it in Rails. Translate the existing Groovy code. Port test suite to RSpec. Refactor, refactor, refactor, refactor, refactor.... Review the spec with the client extensively. Case Study 4 Enable Labs Porting to Rails Part 2 !58 @mark_menard
  • 59. JRuby works today. Java integration lets you play where MRI just can’t go. It’s just Ruby, with Java JVM super powers! Enable Labs !59 @mark_menard
  • 60. Photo credits http://www.flickr.com/photos/usfwsnortheast/5655240564/ http://www.flickr.com/photos/falcon1961/3304306800/ ! Code Color Scheme Solarized Light ! Syntax Highlighting Tool http://www.andre-simon.de/doku/highlight/en/highlight.html Enable Labs !60 @mark_menard
  • 61. Enable Labs @mark_menard http://www.enablelabs.com/ info@enablelabs.com 866-895-8189

×