Your SlideShare is downloading. ×
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus 2011.
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus 2011.

2,423
views

Published on

TorqueBox: The beauty of Ruby with the power of JBoss. Presented at DevNexus 2011 in Atlanta, Georgia.

TorqueBox: The beauty of Ruby with the power of JBoss. Presented at DevNexus 2011 in Atlanta, Georgia.

Published in: Technology

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,423
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
16
Comments
0
Likes
1
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. Bob McWhirter Presented at DevNexus 22 March 2011Creative  Commons  BY-­SA  3.0
  • 2. Bob McWhirter• Project  lead  of  TorqueBox• JBoss  Fellow• Founder  of  The  Codehaus• Founder  of  Drools• Been  with  Red  Hat  ~4  years
  • 3. but its a team.
  • 4. What is TorqueBox?The  mating  of  JRuby  to  JBoss AS.
  • 5. Goals• Support  Ruby  web  frameworks • Rails • Sinatra • Rack• Go  beyond  the  web • Messaging • Jobs • Services
  • 6. But......Java  already  supports  messaging,  jobs  and  services.
  • 7. Thats right.
  • 8. Why Ruby?• No  compilation• Low  ceremony• Highly  expressive• Lots  of  shiny  frameworks• Few  specifications  (more  fun!)• Meta
  • 9. Expressive anything.rbteams.    collect(&:members).    flatten.uniq.each  &:promote!
  • 10. Uhh... com/foo/Anything.javaSet<Person>  people  =  new  HashSet<Person>();;for  (  Team  each  :  teams  )  {    people.addAll(  each.getMembers()  );;}for  (  Person  each  :  people  )  {    each.promote();;}
  • 11. Why JRuby• Very  fast  runtime• Real  threads• Java  libraries• Java  tools• Healthy  community
  • 12. Easy Install. Even on Windows$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.zip$  export  TORQUEBOX_HOME=$PWD/torquebox-­1*$  export  JBOSS_HOME=$TORQUEBOX_HOME/jboss$  export  JRUBY_HOME=$TORQUEBOX_HOME/jruby$  export  PATH=$JRUBY_HOME/bin:$PATH
  • 13. Easy Install. Even on Windows$ wget http://torquebox.org/torquebox-dev.zip$ unzip torquebox-dev.zip$  export  TORQUEBOX_HOME=$PWD/torquebox-­1*$  export  JBOSS_HOME=$TORQUEBOX_HOME/jboss$  export  JRUBY_HOME=$TORQUEBOX_HOME/jruby$  export  PATH=$JRUBY_HOME/bin:$PATH
  • 14. Easy Install. Even on Windows$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.zip$ export TORQUEBOX_HOME=$PWD/torquebox-1*$ export JBOSS_HOME=$TORQUEBOX_HOME/jboss$ export JRUBY_HOME=$TORQUEBOX_HOME/jruby$  export  PATH=$JRUBY_HOME/bin:$PATH
  • 15. Easy Install. Even on Windows$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.zip Make  sure  the  jruby   found  in  your  path  is  in   $JRUBY_HOME/bin.$  export  TORQUEBOX_HOME=$PWD/torquebox-­1*$  export  JBOSS_HOME=$TORQUEBOX_HOME/jboss$  export  JRUBY_HOME=$TORQUEBOX_HOME/jruby$ export PATH=$JRUBY_HOME/bin:$PATH
  • 16. The DetailsBuilds  upon  and  requires  JBoss  AS  6.x.    Tight  integration  with  the  JBoss  stack.
  • 17. The CompetitionWarbler,  Trinidad,  Unicorn,  Thin,  Passenger......all  address  only  the  web  question.
  • 18. WebRun  Ruby  web-­apps  within  the  context  of  the  Servlet  container.    Without compilation.
  • 19. A rails applicationRAILS_ROOT/ Filename    app/        models/            person.rb        views/            person/                index.html.haml                show.html.haml        controllers/            persons_controller.rb    lib/        my-­java-­components.jar    config/        database.yml        torquebox.yml
  • 20. Deploy! Filename$  rake  torquebox:deploy
  • 21. But continue editingDeployment  does  not  create  archives  (by  default).Continue  live-­editing  of  running  app:  models,views,  controllers...
  • 22. Non-surprising.Almost boring.
  • 23. Web (Java Integration) Filenameclass  SomeController    def  index        session[:password]  =  sw0rdfish    endend
  • 24. Web (Java Integration) Filenamepublic  class  SomeServlet  {    public  void  doGet(HttpServletRequest  req,                                        HttpServletResponse  resp)      {        request.getSession().getValue("password");;    }}
  • 25. ClusteringRuby  applications  participate  fully  in  AS  clustering.Can  use  JBoss  mod_cluster.
  • 26. mod_clusterA  reverse  proxy  implemented  as  an  Apache  module  with  JBoss  awareness.  Constantly  gathers  load  statistics  and  deployment  availability  for  intelligent  request  distribution.
  • 27. mod_cluster
  • 28. mod_cluster• Dynamic  configuration• Server-­side  load  factor  calculation• Fine-­grained  web  app  lifecycle• AJP  (Apache  JServ  Protocol)  is   optional.  HTTP[S]  is  also  supported.
  • 29. Lets gobeyond the web...
  • 30. Scheduled Jobs
  • 31. Jobs app/jobs/newsletter_sender.rbclass  NewsletterSender      def run()        subscriptions  =  Subscription.find(:all)        subscriptions.each  do  |e|            send_newsletter(  e  )        end    end  end
  • 32. Jobs config/torquebox.ymljobs:    monthly_newsletter:        description:  first  of  month        job:  NewsletterSender        cron:  ‘0  0  0  1  *  ?’    sandbox:        job:  Sandbox        cron:  ‘*/5  *  *  *  *  ?’
  • 33. Messaging, Part 1 (async tasks)
  • 34. Tasks app/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  payload[:person]          person  ||=  Person.find_by_id(payload[:id])        if  person            #  send  the  email            person.welcomed  =  true            person.save!        end    endend
  • 35. TasksEmailTask.async(:welcome,  payload  )
  • 36. TasksCall  them  from  your  controllers,  models,  and  observers,  or  even  other  tasks.  Even  in  non-­Rails  apps!
  • 37. Messaging, Part 2 (backgroundable)
  • 38. Regular Class Filenameclass  Something    def  foo()    end    def  bar()    endend
  • 39. Blocking invocations Filenamesomething  =  Something.newsomething.foosomething.bar
  • 40. Backgroundable Filenameclass  Something include TorqueBox::Messaging::Backgroundable    def  foo()    end    def  bar()    endend
  • 41. Non-blocking invocations Filenamesomething  =  Something.newsomething.background.foosomething.background.bar
  • 42. Choices Filenameclass  Something    include  TorqueBox::Messaging::Backgroundable always_background :foo    def  foo()    end    def  bar()    endend
  • 43. Just do it right. Filenamesomething  =  Something.newsomething.foo
  • 44. Messaging, Part 3 (low-level)
  • 45. Destinationsconfig/torquebox.ymlqueues:    /queues/questions:    /queues/answers:        durable:  falsetopics:    /topics/new_accounts    /topics/notifications
  • 46. Processorsconfig/torquebox.ymlmessaging: /topics/print: PrintHandler /queues/popular: - PopularHandler - AdultObserver: filter: "age >= 18" concurrency: 5 /queues/students: PrintHandler: config: color: true
  • 47. Processorsapp/models/print_handler.rbinclude  TorqueBox::Messagingclass  PrintHandler  < MessageProcessor    def  initialize(opts)        @color  =  opts[color]    end    def  on_message(body)        puts  "Processing  #{body}  of  #{message}"    endend
  • 48. Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answers  Thread.new  do    req.publish  "What  time  is  it?"    puts  res.receive(  :timeout  =>  1000  )end  puts  req.receiveres.publish  Time.now
  • 49. Queuesexampleinclude TorqueBoxreq = Messaging::Queue.new /queues/questionsres = Messaging::Queue.new /queues/answers  Thread.new  do    req.publish  "What  time  is  it?"    puts  res.receive(  :timeout  =>  1000  )end  puts  req.receiveres.publish  Time.now
  • 50. Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answers  Thread.new do req.publish "What time is it?" puts res.receive( :timeout => 1000 )end  puts  req.receiveres.publish  Time.now
  • 51. Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answers  Thread.new  do    req.publish  "What  time  is  it?"    puts  res.receive(  :timeout  =>  1000  )end  puts req.receiveres.publish Time.now
  • 52. Queues“on the fly”include  TorqueBoxqueue  =  Messaging::Queue.new  /queues/fooqueue.create    ...  queue.destroy
  • 53. Topics• behavior  is  different,  but  interface  is   the  same.• all  subscribers  of  a  topic  see  each   message,  but  only  one  subscriber   will  see  any  message  from  a  queue• use  TorqueBox::Messaging::Topic
  • 54. Servicesrun along, lil’ daemon
  • 55. ServicesLong-­running,  non-­web  “daemons”  that  share  the  runtime  environment  and  deployment  lifecycle  of  your  app.
  • 56. Services• Represented  as  a  class  with   optional  initialize(Hash),   start()  and  stop()  methods,   which  should  each  return  quickly.• Typically  will  start  a  long-­running   loop  in  a  thread  and  respond  to   external  events.
  • 57. Servicesconfig/torquebox.ymlservices:    IrcBot:        server:  freenode.net        channel:  #torquebox        publish:  /topics/irc    MyMudServer:    SomeOtherService:
  • 58. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @queue  =  Messaging::Queue.new(name)    end    def  start          Thread.new  {  run  }      end    def  stop          @done  =  true    endend
  • 59. Servicesapp/{models,etc}/my_service.rbclass  MyService def initialize opts={} name = opts[:publish] @queue = Messaging::Queue.new(name) end    def  start          Thread.new  {  run  }      end    def  stop          @done  =  true    endend
  • 60. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @queue  =  Messaging::Queue.new(name)    end def start Thread.new { run } end    def  stop          @done  =  true    endend
  • 61. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @queue  =  Messaging::Queue.new(name)    end    def  start          Thread.new  {  run  }      end def stop @done = true endend
  • 62. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  run        until  @done            @queue.publish(Time.now)            sleep(1)          end    endend
  • 63. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  run until @done @queue.publish(Time.now) sleep(1) end    endend
  • 64. Caching
  • 65. Caching NoSQLIntegration  with  JBossInfinispan,  a  distributed/replicated  object  store.
  • 66. Transparent InfinispanEasily  used  for  all  of  the  implicit  caching  within  Rails.Replace  in-­memory,  or  memcached  caches.
  • 67. Opaque Infinispan Filenameinclude ActiveSupport::CachemyCache = TorqueBoxStore.new(:name => MyCache, :mode => :replicated, :sync => true)
  • 68. I N J E C T I O N (we must go deeper)
  • 69. Injection?Letting  the  container  figure  out  how  to  help  you  wire  up  complex  component  models.
  • 70. akaInversion of ControlGuice, PicoContainer, JBoss Microcontainer
  • 71. Java CDIpackage  com.mycorp;; Filename@ApplicationScopedclass  Something  { @Inject    private  Else  elsewise;;}@ApplicationScopedclass  Else  {}
  • 72. CDI Injectionclass  MyService    def  initialize  opts={}        @thing  =  cdi(com.mycorp.Something)    endend
  • 73. CDI Injectionclass  MyService    def  initialize  opts={}        @thing  =  cdi(com.mycorp.Something)    endend
  • 74. But theres more thanjust CDI you can inject.Theres also heroin,queues, topics andother things.But not really heroin. (Drugs are bad, mkay?)
  • 75. Destination Injectionclass  MyService    def  initialize  opts={}        @inbound    =  topic(  "/topics/questions"  )        @outbound  =  queue(  "/queues/answers"  )    endend
  • 76. Destination Injectionclass  MyService    def  initialize  opts={}        @inbound    =  topic( "/topics/questions" )        @outbound  =  queue( "/queues/answers" )    endend
  • 77. JNDI Injectionclass  MyService    def  initialize  opts={}        @factory  =  naming("java:comp/env/jdbc/myDS")    endend
  • 78. JNDI Injectionclass  MyService    def  initialize  opts={}        @factory  =  naming("java:comp/env/jdbc/myDS")    endend
  • 79. JBossMC Injectionclass  MyService    def  initialize  opts={}        @heroin  =  mc(  "SomeMCBean"  )    endend
  • 80. JBossMC Injectionclass  MyService    def  initialize  opts={}        @heroin  =  mc( "SomeMCBean" )    endend
  • 81. Why MC Beans?All  internal  plumbing  of  JBoss AS  is  stitched  together  using  MC.    Grab  the  WebServer,  the  CacheManager,  whatevs.
  • 82. But thats not all!
  • 83. BackStageDashboard  to  inspect  and  control  Ruby  components.And  a  RESTful  API.
  • 84. StompBoxEasy  Heroku-­esque  git-­based  deployments.
  • 85. StompBox
  • 86. But how does it perform?
  • 87. BENchmarksReal-world Rail application:RedmineComparisons:TorqueBox,  Trinidad,  Passenger,  Unicorn,  Glassfish,  ThinRuntimes:JRuby,  MRI,  RubyEE
  • 88. RoadmapMay - 1.0.0.FinalThen...    AS7    Authentication    Transactions    Drools/jBPM/etc    Mobicents
  • 89. Resources• http://torquebox.org/• http://github.com/torquebox• #torquebox  on  FreeNode• @torquebox
  • 90. Thanks, and dont forget to pick up some stickers.