TorqueBox
Mixing Java and Ruby all willy-nilly
           Bob McWhirter
            JBoss Fellow
TorqueBox
Mixing Java and Ruby all willy-nilly
           Bob McWhirter
            JBoss Fellow
Who is Bob?
• JBoss Fellow
• Chief Architect of Middleware Cloud
  Computing
• Founder of...
  • The Codehaus
  • Drools
 ...
Basic Premise

• You can run Ruby in the JVM
 • Compliant
 • Fast
• You can wire existing enterprise Java
  features into ...
Why?


• Ruby has a lot of varied point solutions.
• Traditionally web-centric frameworks.
• Performance issues.
What exactly is
 TorqueBox?
TorqueBox
JBoss AS6   Deployers
                        JRuby
JBoss AS6++


Just as good as regular JBoss AS6,
plus the goodness of a Ruby platform.
Ruby Platform

• Ruby Rack (1.1.0)
• JNDI
• JMS (HornetQ)
• Quartz
• VFS
Rack for Web


All Rack applications are supported.

Rails, Sinatra, bare Rack apps.
Rack for Web

Applications can be deployed from
where-ever they sit on disk.

No bundling/jarring is required.
Rack for Web

Using Rack reloading extensions, or Rails’
own development mode, applications can
be modified while running....
Deploying Rails apps
$JBOSS_HOME/server/default/deploy/myapp-rails.yml



 ---
 application:
   RAILS_ROOT: /Users/bob/app...
(But you can bundle)



jar cvf myapp.rails -C myapp/ .
Everything else


Due to lack of specs/standards, we’ve
invented our own APIs for bindings to
JNDI, JMS, Quartz, etc.
Messaging
queues.yml

/queues/foo:
  durable: true

/queues/bar:
  durable: false
Messaging
messaging.tq


subscribe MyConsumer,
          '/queues/foo', :filter=>'...',
          :config=>{
            :...
In a Rails app...

app/                              deploy/
    processors/                       queues.yml
        my_c...
MyConsumer
my_consumer.rb

class MyConsumer < TorqueBox::Message::MessageProcessor

  def on_message(body)
    puts "Proce...
MyConsumer #2
my_consumer.rb

class MyConsumer

  def process!(jms_message)
    puts "Processing #{jms_message.body}”
  en...
MyConsumer #3
my_consumer.rb

class MyConsumer < TorqueBox::Message::MessageProcessor

  def on_message(body)
    puts "Pr...
A client
my_client.rb
#!/usr/bin/env jruby

require 'torquebox/messaging/client'

TorqueBox::Messaging::Client.connect( tr...
A client
my_client.rb
#!/usr/bin/env jruby

require 'torquebox/messaging/client'

TorqueBox::Messaging::Client.connect( tr...
A client
my_client.rb
#!/usr/bin/env jruby

require 'torquebox/messaging/client'

TorqueBox::Messaging::Client.connect( tr...
A client
my_client.rb
#!/usr/bin/env jruby

require 'torquebox/messaging/client'

TorqueBox::Messaging::Client.connect( tr...
A client
my_client.rb
#!/usr/bin/env jruby

require 'torquebox/messaging/client'

TorqueBox::Messaging::Client.connect( tr...
What if I just want a farm
of processors, not lots of
    full AS instances?
TorqueBox
JBossMC + VDF   Deployers
                            JRuby
Messaging outside of AS

trq-message-broker
 • Ruby API for firing up HornetQ

trq-message-processor-host
 • Container for...
trq-message-broker


$ trq-message-broker -s 
    --deploy queues.yml
trq-message-processor-host


$ trq-message-processor-host 
    -N naming.foocorp.com 
    --deploy messaging.tq
What’s going on?
JBossMC and Ruby

•Andrew Lee Rubinger’s
 bootstrap-vdf-minimal
•Large-grained “enablers”
•All from Ruby
Foundation


require 'torquebox/container/foundation'

container = TorqueBox::Container::Foundation.new

container.start
Foundation jboss-beans
<deployment xmlns="urn:jboss:bean-deployer:2.0">


  <bean name="Ruby" class="org.jruby.Ruby">
    ...
Foundation jboss-beans
<deployment xmlns="urn:jboss:bean-deployer:2.0">


  <bean name="Ruby" class="org.jruby.Ruby">
    ...
Foundation jboss-beans
<deployment xmlns="urn:jboss:bean-deployer:2.0">


  <bean name="Ruby" class="org.jruby.Ruby">
    ...
Foundation jboss-beans
<deployment xmlns="urn:jboss:bean-deployer:2.0">


  <bean name="Ruby" class="org.jruby.Ruby">
    ...
Message-Processor Host

require 'torquebox/container/foundation'

container = TorqueBox::Container::Foundation.new

contai...
MPH jboss-beans.xml

<deployment xmlns="urn:jboss:bean-deployer:2.0">

  <classloader><inject bean="JRubyClassLoader"/></c...
MPH jboss-beans.xml

<deployment xmlns="urn:jboss:bean-deployer:2.0">

  <classloader><inject bean="JRubyClassLoader"/></c...
MPH jboss-beans.xml

<deployment xmlns="urn:jboss:bean-deployer:2.0">

  <classloader><inject bean="JRubyClassLoader"/></c...
Pathway
             MyConsumer (rb)




                               Ruby



RubyMessageListener (Java)
           JMS
...
Naming



A lot of things require JNDI.
Naming


In addition to enabling components,
configuration can be included.
Local Naming


container.enable( TorqueBox::Naming::NamingService ) do |config|
    config.export = false
end
Local Naming

<deployment xmlns="urn:jboss:bean-deployer:2.0">

  <bean name="LookupExecutor" class="java.util.concurrent....
Exported Naming


container.enable( TorqueBox::Naming::NamingService ) do |config|
    config.host = "my-other-host.foocor...
Exported Naming
<deployment xmlns="urn:jboss:bean-deployer:2.0">

  <bean name="JNDIServer" class="org.jnp.server.Main">
 ...
Exported Naming
<deployment xmlns="urn:jboss:bean-deployer:2.0">

  <bean name="JNDIServer" class="org.jnp.server.Main">
 ...
VDF bootstrap allows for
TorqueBox bits to be used
  in other environments.
Allows us to boot up an
absolute minimal AS,
     in 1 second.
The same code paths as AS.
JBoss VFS
FS v. VFS
Regular FS          VFS
home/              home/
  bob/               bob/
    my.jar   mount     my.jar/
      ...
Why do we like VFS?
Because there’s more
than just the filesystem
The problem with Ruby



__FILE__
   /path/to/this/file.rb
For Instance...



Dir[ "#{File.dirname(__FILE__)}/*.xml" ]
__FILE__



vfs:/path/to/the/current/file.rb
Making Ruby VFS-aware

Kernel
  open( "vfs:/path/to/some.jar/some/content.txt" )

Dir
  Dir[ "vfs:/path/to/some.jar/some/*...
Now Ruby doesn’t care that
your filesystem is actually VFS.
Bundles


We want Ruby to be happy with
VFS for when you deploy bundles
and hope to farm.
But not warbling



Warbler builds a “normal” JavaEE .war.
So, why bother?
Threading


Unlike C-Ruby, supports
real threading.
Management



RHQ/JON, stuff you're used to.
Integration


HornetQ, Quartz, etc, already
available to your apps.
Gotchas
Native gems


Native gems are not supported,
except FFI.
Threading


While TorqueBox gives you
real threads, many existing
Ruby libraries suck.
Thanks!
Q&A
Resources
http://github.com/torquebox/   # Code
http://torquebox.org/          # Project


#torquebox                     ...
Upcoming SlideShare
Loading in...5
×

JUDCon 2010 Boston : TorqueBox

833

Published on

Presented by Bob McWhirter at JUDCon 2010 in Boston.

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
833
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

JUDCon 2010 Boston : TorqueBox

  1. 1. TorqueBox Mixing Java and Ruby all willy-nilly Bob McWhirter JBoss Fellow
  2. 2. TorqueBox Mixing Java and Ruby all willy-nilly Bob McWhirter JBoss Fellow
  3. 3. Who is Bob? • JBoss Fellow • Chief Architect of Middleware Cloud Computing • Founder of... • The Codehaus • Drools • TorqueBox
  4. 4. Basic Premise • You can run Ruby in the JVM • Compliant • Fast • You can wire existing enterprise Java features into Ruby
  5. 5. Why? • Ruby has a lot of varied point solutions. • Traditionally web-centric frameworks. • Performance issues.
  6. 6. What exactly is TorqueBox?
  7. 7. TorqueBox JBoss AS6 Deployers JRuby
  8. 8. JBoss AS6++ Just as good as regular JBoss AS6, plus the goodness of a Ruby platform.
  9. 9. Ruby Platform • Ruby Rack (1.1.0) • JNDI • JMS (HornetQ) • Quartz • VFS
  10. 10. Rack for Web All Rack applications are supported. Rails, Sinatra, bare Rack apps.
  11. 11. Rack for Web Applications can be deployed from where-ever they sit on disk. No bundling/jarring is required.
  12. 12. Rack for Web Using Rack reloading extensions, or Rails’ own development mode, applications can be modified while running. Without redeploying.
  13. 13. Deploying Rails apps $JBOSS_HOME/server/default/deploy/myapp-rails.yml --- application: RAILS_ROOT: /Users/bob/applications/my_app RAILS_ENV: development web: context: /
  14. 14. (But you can bundle) jar cvf myapp.rails -C myapp/ .
  15. 15. Everything else Due to lack of specs/standards, we’ve invented our own APIs for bindings to JNDI, JMS, Quartz, etc.
  16. 16. Messaging queues.yml /queues/foo: durable: true /queues/bar: durable: false
  17. 17. Messaging messaging.tq subscribe MyConsumer, '/queues/foo', :filter=>'...', :config=>{ :answer=>42 }
  18. 18. In a Rails app... app/ deploy/ processors/ queues.yml my_consumer.rb topics.yml config/ messaging.tq Either queues.yml topics.yml
  19. 19. MyConsumer my_consumer.rb class MyConsumer < TorqueBox::Message::MessageProcessor def on_message(body) puts "Processing #{body}” end end
  20. 20. MyConsumer #2 my_consumer.rb class MyConsumer def process!(jms_message) puts "Processing #{jms_message.body}” end end
  21. 21. MyConsumer #3 my_consumer.rb class MyConsumer < TorqueBox::Message::MessageProcessor def on_message(body) puts "Processing #{body} of #{message}” end end
  22. 22. A client my_client.rb #!/usr/bin/env jruby require 'torquebox/messaging/client' TorqueBox::Messaging::Client.connect( true, :auto, 'localhost' ) do |session| queue = session.createQueue( '/queues/foo' ) producer = session.createProducer( queue ) message = session.createTextMessage( "hello #{Time.now}" ) producer.send( message ) session.commit end
  23. 23. A client my_client.rb #!/usr/bin/env jruby require 'torquebox/messaging/client' TorqueBox::Messaging::Client.connect( true, :auto, 'localhost' ) do |session| queue = session.createQueue( '/queues/foo' ) producer = session.createProducer( queue ) message = session.createTextMessage( "hello #{Time.now}" ) producer.send( message ) session.commit end
  24. 24. A client my_client.rb #!/usr/bin/env jruby require 'torquebox/messaging/client' TorqueBox::Messaging::Client.connect( true, :auto, 'localhost' ) do |session| queue = session.createQueue( '/queues/foo' ) producer = session.createProducer( queue ) message = session.createTextMessage( "hello #{Time.now}" ) producer.send( message ) session.commit end
  25. 25. A client my_client.rb #!/usr/bin/env jruby require 'torquebox/messaging/client' TorqueBox::Messaging::Client.connect( true, :auto, 'localhost' ) do |session| queue = session.createQueue( '/queues/foo' ) producer = session.createProducer( queue ) message = session.createTextMessage( "hello #{Time.now}" ) producer.send( message ) session.commit end
  26. 26. A client my_client.rb #!/usr/bin/env jruby require 'torquebox/messaging/client' TorqueBox::Messaging::Client.connect( true, :auto, 'localhost' ) do |session| queue = session.createQueue( '/queues/foo' ) producer = session.createProducer( queue ) message = session.createTextMessage( "hello #{Time.now}" ) producer.send( message ) session.commit end
  27. 27. What if I just want a farm of processors, not lots of full AS instances?
  28. 28. TorqueBox JBossMC + VDF Deployers JRuby
  29. 29. Messaging outside of AS trq-message-broker • Ruby API for firing up HornetQ trq-message-processor-host • Container for processors.
  30. 30. trq-message-broker $ trq-message-broker -s --deploy queues.yml
  31. 31. trq-message-processor-host $ trq-message-processor-host -N naming.foocorp.com --deploy messaging.tq
  32. 32. What’s going on?
  33. 33. JBossMC and Ruby •Andrew Lee Rubinger’s bootstrap-vdf-minimal •Large-grained “enablers” •All from Ruby
  34. 34. Foundation require 'torquebox/container/foundation' container = TorqueBox::Container::Foundation.new container.start
  35. 35. Foundation jboss-beans <deployment xmlns="urn:jboss:bean-deployer:2.0"> <bean name="Ruby" class="org.jruby.Ruby"> <constructor factoryClass="org.jruby.Ruby" factoryMethod="getGlobalRuntime"/> </bean> <bean name="JRubyClassLoader"> <constructor factoryMethod="getJRubyClassLoader"> <factory bean="Ruby"/> </constructor> </bean> <bean name="RubyRuntimeFactory" class="org.torquebox.interp.core.SingletonRubyRuntimeFactory"> <property name="ruby"> <inject bean="Ruby"/> </property> </bean> <bean name="RuntimePoolDeployer" class="org.torquebox.interp.deployers.RuntimePoolDeployer"/> </deployment>
  36. 36. Foundation jboss-beans <deployment xmlns="urn:jboss:bean-deployer:2.0"> <bean name="Ruby" class="org.jruby.Ruby"> <constructor factoryClass="org.jruby.Ruby" factoryMethod="getGlobalRuntime"/> </bean> <bean name="JRubyClassLoader"> <constructor factoryMethod="getJRubyClassLoader"> <factory bean="Ruby"/> </constructor> </bean> <bean name="RubyRuntimeFactory" class="org.torquebox.interp.core.SingletonRubyRuntimeFactory"> <property name="ruby"> <inject bean="Ruby"/> </property> </bean> <bean name="RuntimePoolDeployer" class="org.torquebox.interp.deployers.RuntimePoolDeployer"/> </deployment>
  37. 37. Foundation jboss-beans <deployment xmlns="urn:jboss:bean-deployer:2.0"> <bean name="Ruby" class="org.jruby.Ruby"> <constructor factoryClass="org.jruby.Ruby" factoryMethod="getGlobalRuntime"/> </bean> <bean name="JRubyClassLoader"> <constructor factoryMethod="getJRubyClassLoader"> <factory bean="Ruby"/> </constructor> </bean> <bean name="RubyRuntimeFactory" class="org.torquebox.interp.core.SingletonRubyRuntimeFactory"> <property name="ruby"> <inject bean="Ruby"/> </property> </bean> <bean name="RuntimePoolDeployer" class="org.torquebox.interp.deployers.RuntimePoolDeployer"/> </deployment>
  38. 38. Foundation jboss-beans <deployment xmlns="urn:jboss:bean-deployer:2.0"> <bean name="Ruby" class="org.jruby.Ruby"> <constructor factoryClass="org.jruby.Ruby" factoryMethod="getGlobalRuntime"/> </bean> <bean name="JRubyClassLoader"> <constructor factoryMethod="getJRubyClassLoader"> <factory bean="Ruby"/> </constructor> </bean> <bean name="RubyRuntimeFactory" class="org.torquebox.interp.core.SingletonRubyRuntimeFactory"> <property name="ruby"> <inject bean="Ruby"/> </property> </bean> <bean name="RuntimePoolDeployer" class="org.torquebox.interp.deployers.RuntimePoolDeployer"/> </deployment>
  39. 39. Message-Processor Host require 'torquebox/container/foundation' container = TorqueBox::Container::Foundation.new container.enable( TorqueBox::Messaging::MessageProcessorHost ) container.start
  40. 40. MPH jboss-beans.xml <deployment xmlns="urn:jboss:bean-deployer:2.0"> <classloader><inject bean="JRubyClassLoader"/></classloader> <bean name="MessageProcessorDeployer" class="org.torquebox.messaging.deployers.MessageProcessorDeployer"/> <bean name="MessagingRuntimePoolDeployer" class="org.torquebox.messaging.deployers.MessagingRuntimePoolDeployer"> <property name="instanceFactoryName">RubyRuntimeFactory</property> </bean> </deployment>
  41. 41. MPH jboss-beans.xml <deployment xmlns="urn:jboss:bean-deployer:2.0"> <classloader><inject bean="JRubyClassLoader"/></classloader> <bean name="MessageProcessorDeployer" class="org.torquebox.messaging.deployers.MessageProcessorDeployer"/> <bean name="MessagingRuntimePoolDeployer" class="org.torquebox.messaging.deployers.MessagingRuntimePoolDeployer"> <property name="instanceFactoryName">RubyRuntimeFactory</property> </bean> </deployment>
  42. 42. MPH jboss-beans.xml <deployment xmlns="urn:jboss:bean-deployer:2.0"> <classloader><inject bean="JRubyClassLoader"/></classloader> <bean name="MessageProcessorDeployer" class="org.torquebox.messaging.deployers.MessageProcessorDeployer"/> <bean name="MessagingRuntimePoolDeployer" class="org.torquebox.messaging.deployers.MessagingRuntimePoolDeployer"> <property name="instanceFactoryName">RubyRuntimeFactory</property> </bean> </deployment>
  43. 43. Pathway MyConsumer (rb) Ruby RubyMessageListener (Java) JMS RubyRuntimePool
  44. 44. Naming A lot of things require JNDI.
  45. 45. Naming In addition to enabling components, configuration can be included.
  46. 46. Local Naming container.enable( TorqueBox::Naming::NamingService ) do |config| config.export = false end
  47. 47. Local Naming <deployment xmlns="urn:jboss:bean-deployer:2.0"> <bean name="LookupExecutor" class="java.util.concurrent.ThreadPoolExecutor"> <constructor factoryMethod="newFixedThreadPool" factoryClass="java.util.concurrent.Executors"> <parameter>2</parameter> </constructor> <stop method="shutdown"/> </bean> <bean name="Naming" class="org.jnp.server.NamingBeanImpl"/> </deployment>
  48. 48. Exported Naming container.enable( TorqueBox::Naming::NamingService ) do |config| config.host = "my-other-host.foocorp.com" config.port = 10990 end
  49. 49. Exported Naming <deployment xmlns="urn:jboss:bean-deployer:2.0"> <bean name="JNDIServer" class="org.jnp.server.Main"> <property name="namingInfo"> <inject bean="Naming"/> </property> <property name="port">${jnp.port:1099}</property> <property name="bindAddress">${jnp.host:localhost}</property> <property name="rmiPort">${jnp.rmiPort:1098}</property> <property name="rmiBindAddress">${jnp.host:localhost}</property> <property name="lookupExector"> <inject bean="LookupExecutor"/> </property> </bean> </deployment>
  50. 50. Exported Naming <deployment xmlns="urn:jboss:bean-deployer:2.0"> <bean name="JNDIServer" class="org.jnp.server.Main"> <property name="namingInfo"> <inject bean="Naming"/> </property> <property name="port">${jnp.port:1099}</property> <property name="bindAddress">${jnp.host:localhost}</property> <property name="rmiPort">${jnp.rmiPort:1098}</property> <property name="rmiBindAddress">${jnp.host:localhost}</property> <property name="lookupExector"> <inject bean="LookupExecutor"/> </property> </bean> </deployment>
  51. 51. VDF bootstrap allows for TorqueBox bits to be used in other environments.
  52. 52. Allows us to boot up an absolute minimal AS, in 1 second.
  53. 53. The same code paths as AS.
  54. 54. JBoss VFS
  55. 55. FS v. VFS Regular FS VFS home/ home/ bob/ bob/ my.jar mount my.jar/ WEB-INF/ lib/ mount another.jar/ META-INF/ manifest.xml
  56. 56. Why do we like VFS?
  57. 57. Because there’s more than just the filesystem
  58. 58. The problem with Ruby __FILE__ /path/to/this/file.rb
  59. 59. For Instance... Dir[ "#{File.dirname(__FILE__)}/*.xml" ]
  60. 60. __FILE__ vfs:/path/to/the/current/file.rb
  61. 61. Making Ruby VFS-aware Kernel open( "vfs:/path/to/some.jar/some/content.txt" ) Dir Dir[ "vfs:/path/to/some.jar/some/*.txt" ] File File.exist?( "vfs:/path/to/some.jar/some/content.txt" ) File.read( "vfs:/path/to/some.jar/some/content.txt" )
  62. 62. Now Ruby doesn’t care that your filesystem is actually VFS.
  63. 63. Bundles We want Ruby to be happy with VFS for when you deploy bundles and hope to farm.
  64. 64. But not warbling Warbler builds a “normal” JavaEE .war.
  65. 65. So, why bother?
  66. 66. Threading Unlike C-Ruby, supports real threading.
  67. 67. Management RHQ/JON, stuff you're used to.
  68. 68. Integration HornetQ, Quartz, etc, already available to your apps.
  69. 69. Gotchas
  70. 70. Native gems Native gems are not supported, except FFI.
  71. 71. Threading While TorqueBox gives you real threads, many existing Ruby libraries suck.
  72. 72. Thanks!
  73. 73. Q&A
  74. 74. Resources http://github.com/torquebox/ # Code http://torquebox.org/ # Project #torquebox # IRC @torquebox # Twitter @bobmcwhirter
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×