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

Like this? Share it with your network

Share

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

  • 2,917 views
Uploaded 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.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
2,917
On Slideshare
2,756
From Embeds
161
Number of Embeds
8

Actions

Shares
Downloads
16
Comments
0
Likes
1

Embeds 161

http://torquebox.org 149
http://planet.jboss.org 5
http://static.slidesharecdn.com 2
http://localhost:4242 1
http://staging.torquebox.org 1
http://planet-stg.jboss.org 1
http://localhost 1
http://web.archive.org 1

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.