The Beauty of Ruby with the Power of Java                                 Toby Crawley                                   O...
Toby  Crawley!• @tcrawley• TorqueBox  Core  Developer• Red  Hat  Senior  Engineer  
but  its  a  team.
What  is  TorqueBox? The  mating  of  JRuby  to   JBoss  AS.
Application  Server?        Sinatra      Rails              Rack        Passenger/Thin        Apache/Nginx
Application  Server?              Sinatra      Rails                    Rack    Tasks     Passenger/Thin  Resque/ DelayedJ...
Application  Server?              Sinatra      Rails                    Rack    Tasks     Passenger/Thin       Jobs  Resqu...
Application  Server?              Sinatra      Rails                    Rack    Tasks     Passenger/Thin       Jobs  Resqu...
TorqueBox  ASSinatra      Rails      Rack            Tasks   Procs            Jobs        Daemons      Web               M...
Goals• Support  Ruby  web  frameworks • Rails • Sinatra • Rack
Goals• Support  Ruby  web  frameworks • Rails • Sinatra • Rack• Go  beyond  the  web • Messaging • Jobs • Services
Goals          No  XML,  No  Java(unless  youre  into  that  sort  of  thing)
Why  Ruby?• No  compilation• Highly  expressive• Lots  of  shiny  frameworks• Few  specifications  (more  fun!)• Meta-­pro...
Expressivecom/foo/Anything.javaSet<Person>  people  =  new  HashSet<Person>();;for  (  Team  each  :  teams  )  {    peopl...
Expressiveanything.rbteams.collect(&:members).  flatten.uniq.each(&:promote)
Expressiveanything.rball_members  =          teams.collect(&:members)all_members.flatten!.uniq!all_members.each(&:promote)
Why  JRuby?
Why  JRuby?system  =  Java::java.lang.Systemsystem.properties.each  do  |k,v|    system.properties[k]  =  v.upcaseend
Why  JRuby?• Very  fast  runtime• Real  threads• Java  libraries• Java  tools• Healthy  community
TorqueBox  Details Builds  upon  and  requires   JBoss  AS  6.x.     Tight  integration  with  the   JBoss  stack.
Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.1-­bin.zip$  export  TORQUEBOX_HOME=$PWD/tor...
Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.0.0-­bin.zip$  export  TORQUEBOX_HOME=$PWD/t...
Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.1-­bin.zip$  export  TORQUEBOX_HOME=$PWD/tor...
Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.1-­bin.zip$  export  TORQUEBOX_HOME=$PWD/tor...
Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.0.0.CR1-­bin.zip                            ...
Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.0.0.CR1-­bin.zip                            ...
Deploymentrake  torquebox:run        Run  TorqueBox  serverrake  torquebox:deploy[context_path]        Deploy  the  app  i...
DeploymentThe  torquebox:deploy  task  creates:$TORQUEBOX_HOME/apps/my-­app.yml
WebRun  Ruby  web-­apps  within  the  context  of  the  Servlet  container.    Without  compilation.
But  continue  editing Continue  live-­editing  of  running   app:   models,views,  controllers...
Non-­surprising.  Almost  boring.
Web  (Session  Integration)class  SomeController    def  index        session[:password]  =  sw0rdfish    endend
Web  (Session  Integration)public  class  SomeServlet  {    public  void  doGet(HttpServletRequest  request,              ...
ClusteringRuby  applications  participate  fully  in  AS  clustering.Can  use  JBoss  mod_cluster.
mod_clusterA  reverse  proxy  implemented  as  an  Apache  module  with  JBoss  awareness.  Constantly  gathers  load  sta...
Lets  go  beyond  the    web...
Jobsapp/jobs/newsletter_sender.rbclass  NewsletterSender      def  run()        subscriptions  =  Subscription.find(:all) ...
Jobsconfig/torquebox.ymljobs:    monthly_newsletter:        description:  first  of  month        job:  NewsletterSender  ...
Regular  Classclass  Something    def  foo    end    def  bar    endend
Blocking  invocationssomething  =  Something.newsomething.foosomething.bar
Backgroundableclass  Something    include  TorqueBox::Messaging::Backgroundable    def  foo    end    def  bar    endend
Explicitly  Non-­blocking  something  =  Something.newsomething.background.foosomething.background.bar
Choicesclass  Something    include  TorqueBox::Messaging::Backgroundable    always_background  :foo    def  foo    end    ...
Implicitly  Non-­blocking  something  =  Something.newsomething.foo
See  The  Futuresomething  =  Something.newfuture  =  something.foo
See  The  Futurefuture.started?future.complete?future.error?future.result
See  The  Futureclass  Something    def  foo        ...        count  +=  1        future.status  =  count        ...    e...
See  The  Future#  on  the  client  sidefuture.status_changed?future.status  #  =>  42
Messaging•   JMS  behind  the  scenes•   HornetQ  is  the  JBoss  JMS      implementation
Destinationsconfig/torquebox.ymlqueues:    /queues/questions:    /queues/answers:        durable:  falsetopics:    /topics...
Processorsapp/models/print_handler.rbinclude  TorqueBox::Messagingclass  PrintHandler  <  MessageProcessor    def  initial...
Processorsconfig/torquebox.ymlmessaging:  /topics/orders:    - PrintHandler    - ShoutHandler  /queues/receipts:    PrintH...
Queuescontrived  examplequestions  =  Queue.new(/queues/questions)answers  =  Queue.new(/queues/answers)  Thread.new  do  ...
Queuescontrived  examplequestions  =  Queue.new(/queues/questions)answers  =  Queue.new(/queues/answers)  Thread.new  do  ...
Queuescontrived  examplequestions  =  Queue.new(/queues/questions)answers  =  Queue.new(/queues/answers)  Thread.new  do  ...
Queuescontrived  examplequestions  =  Queue.new(/queues/questions)answers  =  Queue.new(/queues/answers)  Thread.new  do  ...
Queues“on  the  fly”include  TorqueBox::Messagingqueue  =  Queue.new(/queues/foo)queue.create    ...  queue.destroy
Topics• behavior  is  different,  but  interface  is    the  same.• all  subscribers  of  a  topic  see  each    message, ...
ServicesLong-­running,  non-­web  “daemons”  that  share  the  runtime  environment  and  deployment  lifecycle  of  your ...
Services• Represented  as  a  class  with    optional  initialize(Hash),      start()  and  stop()  methods,      which  s...
Servicesconfig/torquebox.ymlservices:    TimeMachine:        queue:  /queue/morris_day    IrcBot:        server:  freenode...
Services app/services/time_machine.rbclass  TimeMachine    def  initialize(opts)        @queue  =  Queue.new(opts[queue]) ...
Servicesapp/services/time_machine.rbclass  TimeMachine    def  initialize(opts)        @queue  =  Queue.new(opts[queue])  ...
Servicesapp/services/time_machine.rbclass  TimeMachine    def  initialize(opts)        @queue  =  Queue.new(opts[queue])  ...
Servicesapp/services/time_machine.rbclass  TimeMachine    def  initialize(opts)        @queue  =  Queue.new(opts[queue])  ...
Servicesapp/services/time_machine.rbclass  TimeMachine    def  run          until  @done            @queue.publish(Time.no...
Servicesapp/services/time_machine.rbclass  TimeMachine    def  run          until  @done            @queue.publish(Time.no...
CachingIntegration  with  JBoss  Infinispan,  a  distributed/replicated  object  store.
Transparent  Infinispan Easily  used  for  all  of  the   implicit  caching  within   Rails. Replace  in-­memory,  or   me...
Opaque  Infinispaninclude ActiveSupport::CachemyCache =  TorqueBoxStore.new(:name => MyCache,                     :mode =>...
Injection? Letting  the  container  figure   out  how  to  help  you  wire   up  complex  component   models.
aka   Inversion  of  ControlGuice, PicoContainer, JBoss Microcontainer
Java  CDIpackage  com.mycorp;;@ApplicationScopedclass  Something  {    @Inject    private  SomethingElse  elsewise;;}@Appl...
CDI  Injectionclass  MyService    include  TorqueBox::Injectors    def  initialize  opts={}        @thing  =  inject(com.m...
But  theres  more  than  just  CDI  you  can  inject.    Theres  also  queues,  topics,  heroin  and  other  things.    
Destination  Injectionclass  MyService    include  TorqueBox::Injectors    def  initialize  opts={}        @inbound    =  ...
JNDI  Injectionclass  MyService    include  TorqueBox::Injectors    def  initialize  opts={}        @factory  =  inject("j...
JBossMC  Injectionclass  MyService    include  TorqueBox::Injectors    def  initialize  opts={}        @heroin  =  inject(...
Why  MC  Beans?All  internal  plumbing  of  JBoss  AS  is  stitched  together  using  MC.    Grab  the  WebServer,  the  C...
BENchmarksReal-­world  Rail  application:RedmineComparisons:TorqueBox,  Trinidad,  Glassfish,  Passenger,  Unicorn,  ThinR...
BackStageDashboard  to  inspect  and  control  Ruby  components.And  a  RESTful  API.
StompBoxEasy  Heroku-­esque  git-­based  deployments.
Oh  yeah... It  works  on  Windows.
Roadmap1.1  Stable2.0  Development  (based  on    JBoss  AS7)???  -­  you  tell  us
Resources•   http://torquebox.org/•   http://github.com/torquebox•   #torquebox  on  FreeNode•   @torquebox
Thanks!                                                         Questions?                        Image  attributions:    ...
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
Upcoming SlideShare
Loading in …5
×

Torquebox OSCON Java 2011

3,041 views
2,948 views

Published on

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

  • Be the first to like this

No Downloads
Views
Total views
3,041
On SlideShare
0
From Embeds
0
Number of Embeds
1,173
Actions
Shares
0
Downloads
22
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Torquebox OSCON Java 2011

  1. 1. The Beauty of Ruby with the Power of Java Toby Crawley OSCON JavaCreative  Commons  BY-­SA  3.0 July 2011
  2. 2. Toby  Crawley!• @tcrawley• TorqueBox  Core  Developer• Red  Hat  Senior  Engineer  
  3. 3. but  its  a  team.
  4. 4. What  is  TorqueBox? The  mating  of  JRuby  to   JBoss  AS.
  5. 5. Application  Server? Sinatra Rails Rack Passenger/Thin Apache/Nginx
  6. 6. Application  Server? Sinatra Rails Rack Tasks Passenger/Thin Resque/ DelayedJob Apache/Nginx
  7. 7. Application  Server? Sinatra Rails Rack Tasks Passenger/Thin Jobs Resque/ DelayedJob Apache/Nginx crond
  8. 8. Application  Server? Sinatra Rails Rack Tasks Passenger/Thin Jobs Resque/ DelayedJob Apache/Nginx crond Daemons god/monit
  9. 9. TorqueBox  ASSinatra Rails Rack Tasks Procs Jobs Daemons Web Messaging Scheduling Services JBoss AS Clustering Load Balancing HA
  10. 10. Goals• Support  Ruby  web  frameworks • Rails • Sinatra • Rack
  11. 11. Goals• Support  Ruby  web  frameworks • Rails • Sinatra • Rack• Go  beyond  the  web • Messaging • Jobs • Services
  12. 12. Goals No  XML,  No  Java(unless  youre  into  that  sort  of  thing)
  13. 13. Why  Ruby?• No  compilation• Highly  expressive• Lots  of  shiny  frameworks• Few  specifications  (more  fun!)• Meta-­programming
  14. 14. Expressivecom/foo/Anything.javaSet<Person>  people  =  new  HashSet<Person>();;for  (  Team  each  :  teams  )  {    people.addAll(  each.getMembers()  );;}for  (  Person  each  :  people  )  {    each.promote();;}
  15. 15. Expressiveanything.rbteams.collect(&:members).  flatten.uniq.each(&:promote)
  16. 16. Expressiveanything.rball_members  =          teams.collect(&:members)all_members.flatten!.uniq!all_members.each(&:promote)
  17. 17. Why  JRuby?
  18. 18. Why  JRuby?system  =  Java::java.lang.Systemsystem.properties.each  do  |k,v|    system.properties[k]  =  v.upcaseend
  19. 19. Why  JRuby?• Very  fast  runtime• Real  threads• Java  libraries• Java  tools• Healthy  community
  20. 20. TorqueBox  Details Builds  upon  and  requires   JBoss  AS  6.x.     Tight  integration  with  the   JBoss  stack.
  21. 21. Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.1-­bin.zip$  export  TORQUEBOX_HOME=$PWD/torquebox-­1.1$  export  JBOSS_HOME=$TORQUEBOX_HOME/jboss$  export  JRUBY_HOME=$TORQUEBOX_HOME/jruby$  export  PATH=$JRUBY_HOME/bin:$PATH
  22. 22. Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.0.0-­bin.zip$  export  TORQUEBOX_HOME=$PWD/torquebox-­1.1$  export  JBOSS_HOME=$TORQUEBOX_HOME/jboss$  export  JRUBY_HOME=$TORQUEBOX_HOME/jruby$  export  PATH=$JRUBY_HOME/bin:$PATH
  23. 23. Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.1-­bin.zip$  export  TORQUEBOX_HOME=$PWD/torquebox-­1.1$  export  JBOSS_HOME=$TORQUEBOX_HOME/jboss$  export  JRUBY_HOME=$TORQUEBOX_HOME/jruby$  export  PATH=$JRUBY_HOME/bin:$PATH
  24. 24. Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.1-­bin.zip$  export  TORQUEBOX_HOME=$PWD/torquebox-­1.1$  export  JBOSS_HOME=$TORQUEBOX_HOME/jboss$  export  JRUBY_HOME=$TORQUEBOX_HOME/jruby$  export  PATH=$JRUBY_HOME/bin:$PATH
  25. 25. Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.0.0.CR1-­bin.zip Make  sure  the  jruby   found  in  your  path  is  in  $  export  TORQUEBOX_HOME=$PWD/torquebox-­1* $JRUBY_HOME/bin.$  export  JBOSS_HOME=$TORQUEBOX_HOME/jboss$  export  JRUBY_HOME=$TORQUEBOX_HOME/jruby$  export  PATH=$JRUBY_HOME/bin:$PATH
  26. 26. Easy  Install(download  1.1  from  torquebox.org)$  unzip  torquebox-­dist-­1.0.0.CR1-­bin.zip Make  sure  the  jruby   found  in  your  path  is  in  $  export  TORQUEBOX_HOME=$PWD/torquebox-­1* $JRUBY_HOME/bin.$  export  JBOSS_HOME=$TORQUEBOX_HOME/jboss$  export  JRUBY_HOME=$TORQUEBOX_HOME/jruby$  export  PATH=$JRUBY_HOME/bin:$PATH
  27. 27. Deploymentrake  torquebox:run        Run  TorqueBox  serverrake  torquebox:deploy[context_path]        Deploy  the  app  in  the  current  directoryrake  torquebox:undeploy        Undeploy  the  app  in  the  current  directory
  28. 28. DeploymentThe  torquebox:deploy  task  creates:$TORQUEBOX_HOME/apps/my-­app.yml
  29. 29. WebRun  Ruby  web-­apps  within  the  context  of  the  Servlet  container.    Without  compilation.
  30. 30. But  continue  editing Continue  live-­editing  of  running   app:   models,views,  controllers...
  31. 31. Non-­surprising.  Almost  boring.
  32. 32. Web  (Session  Integration)class  SomeController    def  index        session[:password]  =  sw0rdfish    endend
  33. 33. Web  (Session  Integration)public  class  SomeServlet  {    public  void  doGet(HttpServletRequest  request,                                        HttpServletResponse  resp)  {        request.getSession().getValue("password");;        }}
  34. 34. ClusteringRuby  applications  participate  fully  in  AS  clustering.Can  use  JBoss  mod_cluster.
  35. 35. mod_clusterA  reverse  proxy  implemented  as  an  Apache  module  with  JBoss  awareness.  Constantly  gathers  load  statistics  and  deployment  availability  for  intelligent  request  distribution.
  36. 36. Lets  go  beyond  the   web...
  37. 37. Jobsapp/jobs/newsletter_sender.rbclass  NewsletterSender      def  run()        subscriptions  =  Subscription.find(:all)        subscriptions.each  do  |e|            send_newsletter(e)        end    end  end
  38. 38. Jobsconfig/torquebox.ymljobs:    monthly_newsletter:        description:  first  of  month        job:  NewsletterSender        cron:  ‘0  0  0  1  *  ?’    process_tps_reports:        job:  TPSReportProcessor        cron:  ‘0  0  0  0  MON  ?’        singleton:  true
  39. 39. Regular  Classclass  Something    def  foo    end    def  bar    endend
  40. 40. Blocking  invocationssomething  =  Something.newsomething.foosomething.bar
  41. 41. Backgroundableclass  Something    include  TorqueBox::Messaging::Backgroundable    def  foo    end    def  bar    endend
  42. 42. Explicitly  Non-­blocking  something  =  Something.newsomething.background.foosomething.background.bar
  43. 43. Choicesclass  Something    include  TorqueBox::Messaging::Backgroundable    always_background  :foo    def  foo    end    def  bar    endend
  44. 44. Implicitly  Non-­blocking  something  =  Something.newsomething.foo
  45. 45. See  The  Futuresomething  =  Something.newfuture  =  something.foo
  46. 46. See  The  Futurefuture.started?future.complete?future.error?future.result
  47. 47. See  The  Futureclass  Something    def  foo        ...        count  +=  1        future.status  =  count        ...    endend  
  48. 48. See  The  Future#  on  the  client  sidefuture.status_changed?future.status  #  =>  42
  49. 49. Messaging• JMS  behind  the  scenes• HornetQ  is  the  JBoss  JMS   implementation
  50. 50. Destinationsconfig/torquebox.ymlqueues:    /queues/questions:    /queues/answers:        durable:  falsetopics:    /topics/new_accounts    /topics/notifications
  51. 51. Processorsapp/models/print_handler.rbinclude  TorqueBox::Messagingclass  PrintHandler  <  MessageProcessor    def  initialize(opts)        @printer  =  opts[printer]  ||  default    end    def  on_message(body)        puts  "Processing  #{body}  of  #{message}"    endend
  52. 52. Processorsconfig/torquebox.ymlmessaging: /topics/orders: - PrintHandler - ShoutHandler /queues/receipts: PrintHandler: concurrency: 5 config: printer: the_little_one
  53. 53. Queuescontrived  examplequestions  =  Queue.new(/queues/questions)answers  =  Queue.new(/queues/answers)  Thread.new  do    questions.publish(  "What  time  is  it?"  )    puts  answers.receive(  :timeout  =>  1000  )end  puts  questions.receiveanswers.publish(  Time.now  )
  54. 54. Queuescontrived  examplequestions  =  Queue.new(/queues/questions)answers  =  Queue.new(/queues/answers)  Thread.new  do    questions.publish(  "What  time  is  it?"  )    puts  answers.receive(  :timeout  =>  1000  )end  puts  questions.receiveanswers.publish(  Time.now  )
  55. 55. Queuescontrived  examplequestions  =  Queue.new(/queues/questions)answers  =  Queue.new(/queues/answers)  Thread.new  do    questions.publish(  "What  time  is  it?"  )    puts  answers.receive(  :timeout  =>  1000  )end  puts  questions.receiveanswers.publish(  Time.now  )
  56. 56. Queuescontrived  examplequestions  =  Queue.new(/queues/questions)answers  =  Queue.new(/queues/answers)  Thread.new  do    questions.publish(  "What  time  is  it?"  )    puts  answers.receive(  :timeout  =>  1000  )end  puts  questions.receiveanswers.publish(  Time.now  )
  57. 57. Queues“on  the  fly”include  TorqueBox::Messagingqueue  =  Queue.new(/queues/foo)queue.create    ...  queue.destroy
  58. 58. 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
  59. 59. ServicesLong-­running,  non-­web  “daemons”  that  share  the  runtime  environment  and  deployment  lifecycle  of  your  app.
  60. 60. 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.
  61. 61. Servicesconfig/torquebox.ymlservices:    TimeMachine:        queue:  /queue/morris_day    IrcBot:        server:  freenode.net        channel:  #torquebox        publish:  /topics/irc        singleton:  true
  62. 62. Services app/services/time_machine.rbclass  TimeMachine    def  initialize(opts)        @queue  =  Queue.new(opts[queue])    end    def  start          Thread.new  {  run  }    end    def  stop        @done  =  true      endend
  63. 63. Servicesapp/services/time_machine.rbclass  TimeMachine    def  initialize(opts)        @queue  =  Queue.new(opts[queue])    end    def  start          Thread.new  {  run  }    end    def  stop        @done  =  true    endend
  64. 64. Servicesapp/services/time_machine.rbclass  TimeMachine    def  initialize(opts)        @queue  =  Queue.new(opts[queue])    end    def  start          Thread.new  {  run  }    end    def  stop        @done  =  true    endend
  65. 65. Servicesapp/services/time_machine.rbclass  TimeMachine    def  initialize(opts)        @queue  =  Queue.new(opts[queue])    end    def  start          Thread.new  {  run  }    end    def  stop        @done  =  true    endend
  66. 66. Servicesapp/services/time_machine.rbclass  TimeMachine    def  run          until  @done            @queue.publish(Time.now)            sleep(1)          end    endend
  67. 67. Servicesapp/services/time_machine.rbclass  TimeMachine    def  run          until  @done            @queue.publish(Time.now)            sleep(1)          end    endend
  68. 68. CachingIntegration  with  JBoss  Infinispan,  a  distributed/replicated  object  store.
  69. 69. Transparent  Infinispan Easily  used  for  all  of  the   implicit  caching  within   Rails. Replace  in-­memory,  or   memcached  caches.
  70. 70. Opaque  Infinispaninclude ActiveSupport::CachemyCache = TorqueBoxStore.new(:name => MyCache, :mode => :replicated, :sync => true)
  71. 71. Injection? Letting  the  container  figure   out  how  to  help  you  wire   up  complex  component   models.
  72. 72. aka Inversion  of  ControlGuice, PicoContainer, JBoss Microcontainer
  73. 73. Java  CDIpackage  com.mycorp;;@ApplicationScopedclass  Something  {    @Inject    private  SomethingElse  elsewise;;}@ApplicationScopedclass  SomethingElse  {}
  74. 74. CDI  Injectionclass  MyService    include  TorqueBox::Injectors    def  initialize  opts={}        @thing  =  inject(com.mycorp.Something)    endend
  75. 75. But  theres  more  than  just  CDI  you  can  inject.    Theres  also  queues,  topics,  heroin  and  other  things.    
  76. 76. Destination  Injectionclass  MyService    include  TorqueBox::Injectors    def  initialize  opts={}        @inbound    =  inject("/topics/questions")        @outbound  =  inject("/queues/answers")    endend
  77. 77. JNDI  Injectionclass  MyService    include  TorqueBox::Injectors    def  initialize  opts={}        @factory  =  inject("java:comp/env/jdbc/myDS")    endend
  78. 78. JBossMC  Injectionclass  MyService    include  TorqueBox::Injectors    def  initialize  opts={}        @heroin  =  inject("SomeMCBean")    endend
  79. 79. Why  MC  Beans?All  internal  plumbing  of  JBoss  AS  is  stitched  together  using  MC.    Grab  the  WebServer,  the  CacheManager,  whatevs.
  80. 80. BENchmarksReal-­world  Rail  application:RedmineComparisons:TorqueBox,  Trinidad,  Glassfish,  Passenger,  Unicorn,  ThinRuntimes:JRuby,  MRI,  RubyEE
  81. 81. BackStageDashboard  to  inspect  and  control  Ruby  components.And  a  RESTful  API.
  82. 82. StompBoxEasy  Heroku-­esque  git-­based  deployments.
  83. 83. Oh  yeah... It  works  on  Windows.
  84. 84. Roadmap1.1  Stable2.0  Development  (based  on    JBoss  AS7)???  -­  you  tell  us
  85. 85. Resources• http://torquebox.org/• http://github.com/torquebox• #torquebox  on  FreeNode• @torquebox
  86. 86. Thanks! Questions?                        Image  attributions: Target  by  Jasper  Johns  by  nostri-­imago  http://www.flickr.com/photos/nostri-­imago/3137422976/  CC  BY  2.0 WEB 2.0 HAS AN API  by  raster  http://www.flickr.com/photos/raster/137506981/  CC  BY-­NC-­SA  2.0 Clock  by  Earls37a  http://www.flickr.com/photos/indraw/4857101224/  CC  BY-­SA  2.0 Sink.  by  _Fidelio_  http://www.flickr.com/photos/photogaby/4129740673/  CC  BY  2.0  Huge Queue 1  by  danacea  http://www.flickr.com/photos/danacea/2981199996/  CC  BY-­NC  2.0 Service as a Strategy Celebration at NCVS 2011  by  Be  The  Change,  Inc  http://www.flickr.com/photos/bethechangeinc/5816393052/  CC  BY-­NC  2.0 Cash  by  ROSS  HONG  KONG  http://www.flickr.com/photos/rossap/2716531616/  CC  BY-­NC-­SA  2.0 Injection  by  Dr  Case  http://www.flickr.com/photos/justin_case/3252846177/  CC  BY-­NC  2.0 IMG_1478  by  akshaydavis  http://www.flickr.com/photos/akshaydavis/166391476/  CC  BY-­NC-­SA  2.0 Rainforest  by  Chris.Gray  http://www.flickr.com/photos/chriscgray/3946304802/  CC  BY-­NC-­SA  2.0 Community  by  niallkennedy  http://www.flickr.com/photos/niallkennedy/40727794/  CC  BY-­NC  2.0

×