# TorqueBox # Crossing the line between Java and Ruby ### Rock'n Rails 2012
# @abstractj
![dynjs](img/dynjs.png)
![torquebox](img/torquebox.png)
![oss](img/opensource.png)
![redhat](img/redhat.png)
![aerogear](img/aerogear_logo.png)
# Disclaimer
# Java ![](img/darth.png) ## 927 JSRs only :)
# Expressive? import java.util.Calendar; public class Beer { private Long beerId; private String description; private Calendar createdAt; public Long getBeerId() { return beerId; } public void setBeerId(Long beerId) { this.beerId = beerId; } public String getDescription() { return description; } ... }
# Enterprise

WAR JAX-RPC Struts Spring JAAS EJB JNI EAR SOA JPQL CDI GWT JAX-WS JSF JavaFX JNDI RMI JMX JAXP JAXB JDO JAX-RS JAXR JSTL StAX JAF JDOM AWT Swing JEE JSE JCP JVM JME NIO JSP JRE POJO JavaBean EJBQL

# But it works! ![](img/mei.png)
# Programming
It's all about choosing the right tool for the job and leveraging it correctly - Neal Ford
# JVM

Scala

Jython

Clojure

DynJS

Rhino

Groovy

# Ruby class Beer attr_accessor :beer_id, :description, :created_at end
# DRY ![dry](img/sparta.png)
It is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail - Abraham Maslow
# JRuby ## Java + Ruby on Steroids
# JRuby require 'java' pdf = com.itextpdf.text.Document.new para = com.itextpdf.text.Paragraph.new 'Brought to you by JRuby' file = java.io.FileOutputStream.new 'pdf_demo.pdf' com.itextpdf.text.pdf.PdfWriter.get_instance pdf, file pdf.open pdf.add para pdf.close
# JRuby
You get true multithreading that can use all your computer’s cores from one process, plus a virtual machine that’s been tuned for a decade and a half.
###### *Using JRuby - Bringing Ruby to Java*
# Server Side
# Ruby App ![](img/rubyapp_apache.png)
# Ruby App ![](img/rubyapp_apache.png) ![](img/rubyapp_crond.png)
# Ruby App ![](img/rubyapp_resque.png) ![](img/rubyapp_apache.png) ![](img/rubyapp_crond.png)
# Ruby App ![](img/rubyapp_resque.png) ![](img/rubyapp_apache.png) ![](img/rubyapp_crond.png) ![](img/rubyapp_monit.png)
# JBoss ## Web
# JBoss ## HornetQ
# JBoss ## Scheduling
# JBoss ## Clustering
# AS7

Low memory footprint

Modular class loading

Fast startup time

EE6 compliant

# TorqueBox
The power of JBoss with the expressiveness of Ruby Jim Crossley - MagicRuby Conference
# TorqueBox ![](img/torquebox_stack.png)
# Setup ## From scratch
# Requirements ➜ java -version java version "1.6.0_07" Java(TM) SE Runtime Environment Java HotSpot(TM) 64-Bit Server VM
# GEM ➜ jruby -S gem install torquebox \ torquebox-capistrano-support
# Download ➜ wget http://torquebox.org/release/org/torquebox/torquebox-dist/2.0.3/torquebox-dist-2.0.3-bin.zip ➜ unzip torquebox-dist-2.0.3-bin.zip ➜ export TORQUEBOX_HOME=$PWD/torquebox-dist-2.0.3 ➜ export JBOSS_HOME=$TORQUEBOX_HOME/jboss ➜ export JRUBY_HOME=$TORQUEBOX_HOME/jruby ➜ export PATH=$JRUBY_HOME/bin:$PATH
# Rails rails new beer -m $TORQUEBOX_HOME/share/rails/template.rb
# Folder structure ![](img/server_folder_structure.png)
# Rake tasks ### rake torquebox:deploy ### rake torquebox:undeploy ### rake torquebox:run
# Deployment ## Make knobs, not WAR!
# beer-knob.yml ### application: root: /Users/abstractj/rockandrails/beer environment: development
![](img/idont.png)
# Application ![](img/app_folder_structure.png)
# Gemfile source 'http://rubygems.org' gem 'rails', '3.1.1' gem 'activerecord-jdbcsqlite3-adapter' gem 'jruby-openssl' gem 'json' gem 'jquery-rails' gem 'torquebox-rake-support', '2.0.3' gem 'torquebox', '2.0.3'
# Web ## Rack, Sinatra, Rails
# Caching
class BeersController < ApplicationController 
  caches_action :most_popular, :expires_in => 30.seconds 
  def most_popular 
    @popular_beers = Beer.most_popular(:limit => 25) 
  end 
end
![](img/kidding.png)
# Clustering ### ➜ torquebox run --clustered
# Internals
We write Java so you don't have to
### Patches are always welcome :)
# Internals
class TorqueBoxCommand < Thor 
            map "run" => "start" 
            method_option :clustered, :type => :boolean, 

            def start 
              setup_environment 
              TorqueBox::DeployUtils.run_server(:clustered => options.clustered, 
              :max_threads => options['max-threads'], 
              :bind_address => options['bind-address']) 
            end
          end
# Distributed cache!
# mod_cluster ## httpd-based load balancer
# Infinispan ## Caching
# Invalidation ![](img/infinispan_invalidation1.png)
# Invalidation ![](img/infinispan_invalidation2.png)
# ../application.rb
module Beer 
            class Application < Rails::Application 
              config.cache_store = :torque_box_store
            end 
          end
# Replicated ![](img/infinispan_replicated.png)
# ../application.rb
module Beer 

            class Application < Rails::Application 
              config.cache_store = :torque_box_store, {
              :mode => replicated, :sync =>false
            end
          end
# Job Scheduling
# Internals
Ruby ruby = null; 
          try { 
            ruby = this.runtimePool.borrowRuntime( resolver.getComponentName()); 
            JobComponent job = (JobComponent)resolver.resolve( ruby ); 
            job.run(); //Call ruby method
          } catch (Exception e) { 
              throw new JobExecutionException( e ); 
          } finally { 
            if (ruby != null) { 
              this.runtimePool.returnRuntime( ruby ); 
          } 
          }
# ../app/jobs class JobDemo def initialize # Initialization code end def run # What should be executed end end
# ../torquebox.yml jobs: send_email: job: EmailJob cron: '0 */5 * * * ?' singleton: true config: enviar: true
# Messaging ## Java Messaging Service + HornetQ
# Warning
# Greenfield ## REST + NoSQL ![](img/greenfield.png)
# Real World ![](img/realworld.png)
# ../torquebox.yml /topics/beerTopic: /queues/queueBeer:
# Tasks
class EmailerTask < TorqueBox::Messaging::Task 
              def send_welcome(payload) 
                to = "#{payload[:name]} <#{payload[:address]}>" 
                # send welcome email to the user 
              end 
          end
          
# Tasks
class UserController < ApplicationController 
            def register 
              user = User.new(params[:user]) 

              EmailerTask.async(:send_welcome, :address => user.email, 
              :name => user.name) 
            end 
          end
# Processors
include TorqueBox::Messaging 
          class PrintHandler < MessageProcessor 
            def on_message(body) 
              puts "Processing #{body} of #{message}" 
            end 
            def configure(opts) 
              @color = opts['color'] 
            end 
          end
# Queues
include TorqueBox 
          req = Messaging::Queue.new '/queues/questions' 
          res = Messaging::Queue.new '/queues/answers' 
            
          Thread.new do 
            req.publish "What time is it?" 
            puts res.receive( :timeout => 1000 ) 
          end
# Future ![](img/future.png)
# Future
class EmailerTask
  def send_welcome(payload) 
    to = "#{payload[:name]} <#{payload[:address]}>" 
    # long running task 
  end 
end
# Future
class EmailerTask
          include TorqueBox::Messaging::Backgroundable
          always_background :send_welcome

            def send_welcome(payload) 
              to = "#{payload[:name]} <#{payload[:address]}>" 
              # long running task 
            end 
          end
# Future future = @emailTask.send_welcome(:send_welcome) future.started? future.complete? future.error? future.result future.result(10000)
# Services
# Services
class BeerService 
            def initialize 
              @queue = Messaging::Queue.new(“beer”)
            end
            def start 
              @queue.publish “Buy me a beer” 
            end 
            def stop 
              # What happens when the service stops 
            end 
          end
# Singleton Services ![](img/singleton_services1.png)
# Singleton Services ![](img/singleton_services2.png)
# Services ➜ torquebox run --clustered ## torquebox.yml
services:
  BeerService:
    config:
    singleton: true
# CDI ## Dependency Injection
# WAT?!
# Java
package br.com.rockandrails;

          @ApplicationScoped
          public class Beer {  
              //gets e sets 
            public void say(String message)  { // Some code here
### Jar deployment
app/
          lib/beer.jar
          models/
          views/
          controllers/
# Ruby
class BeerController < ApplicationController

          include TorqueBox::Injectors

              def create
                beer = inject( Java::br.com.rockandrails.Beer ) 
                beer.say “Inject my beer!”
              end

          end
# JNDI
class MyService 
              include TorqueBox::Injectors 

              def initialize opts={} 
                @factory = inject("java:comp/env/jdbc/myDB") 
              end 
          end
# Destinations
class MyService 
          include TorqueBox::Injectors
              def initialize opts={} 
                @inbound = inject("/topic/beerpub")
                @outbound = inject("/queue/beer") 
              end 
          end
# WebSockets with Stomplets
# Stomplets

require 'torquebox-stomp'

class BeerStomplet < TorqueBox::Stomp::JmsStomplet
  
  def configure(options)
    super
    @queue = TorqueBox::Messaging::Queue.new( options['/queue/beer'] )
  end
  
  def on_subscribe(subscriber)
    # session is available via subscriber.session
    subscribe_to( subscriber, @queue )
  end
  
end
# Client
var url = "ws://localhost:8675/stomp";
          var client = Stomp.client(url);
          client.connect(login, passcode, connect_callback);

          connect_callback = function() {
          // called back after the client is connected to the STOMP server
          };
### Thanks @jmesnil! [http://www.jmesnil.net/stomp-websocket/doc/](http://www.jmesnil.net/stomp-websocket/doc/)
# Authentication ## JAAS
# Thanks @abstractj! ## We have Devise!
# Authentication ### torquebox.yml ou auth.yml
auth:
default:
  domain: torquebox
  credentials:
    homer: simpson
#### Authentication
require 'torquebox'
          require 'torquebox-security'
          class LoginController < ApplicationController
              def create
                usuario = params[:usuario]
                senha = params[:senha]

                redirect_to login_path if usuario.blank? || senha.blank?
                authenticator = TorqueBox::Authentication.default

                if authenticator.authenticate(usuario, senha)
                  puts "Autenticado com sucesso"
                  redirect_to contatos_path
                else 
                  mensagem = "Nao autorizado"
                  redirect_to login_path
                end
              end
          end
# Transactions ![](img/transactions.png) ### XA Distributed, multi resource transaction
# XA (2PC) * HornetQ ✔> * Infinispan ✔ * TorqueBox + ActiveRecord ✔
# BackStage ![](img/backstage1.png) ![](img/backstage2.png)
# Stomp Box ## TorqueBox deployment support
![](img/stompbox.png)
# What’s next?
# Polyglot ![](img/polyglot.png)
### DynJS development ![](img/github-dynjs.png)
# ASJS ## JBoss + JavaScript ### on steroids
# Try it yourself! * [TorqueBox 2.0 Installation - http://vimeo.com/33299335](http://vimeo.com/33299335) ## Examples * [https://github.com/abstractj/torquebox-exemplos](https://github.com/abstractj/torquebox-exemplos) * [https://github.com/aerogear/kitchensink-torquebox-mobile](https://github.com/aerogear/kitchensink-torquebox-mobile) * [https://github.com/tobias/rubyconfbr-demo](https://github.com/tobias/rubyconfbr-demo)
# Community ## irc.freenode.net: ### #aerogear, #torquebox * [http://jboss.org/aerogear](http://jboss.org/aerogear) * [@aerogears](http://twitter.com/aerogears) on Twitter
# Thanks [http://github.com/abstractj](http://github.com/abstractj)