Post on 09-May-2015
Creative Commons BY-SA 3.0
When Java meets Ruby
Thursday, December 8, 11
@abstractjJava há 12 anos, Ruby n00bTorqueBox ContributorDynJS ContributorCaelum & ConcreteS
Thursday, December 8, 11
DISCLAIMER
Thursday, December 8, 11
nooooooooooooooo!
Java
927 JSRS!
Thursday, December 8, 11
Expressiva?
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; } public void setDescription(String description) { this.description = description; } public Calendar getCreatedAt() { return createdAt; } public void setCreatedAt(Calendar createdAt) { this.createdAt = createdAt; } } Thursday, December 8, 11
ENTERPRISE
Thursday, December 8, 11
ENTERPRISEWAR
JAX-RPC
StrutsSpring
JAAS
EJB
JNI
EAR
SOA
JAX-WS
JSF
Java-FX
JNDIRMI
JMX
JAXP
JAXB JDOJAX-RS
JAXR JSTL StAX
JAF
JDOMAWTSwing
JEE
JSE
JCP
JVM JME
NIO JSP
JREPOJO
JavaBean
EJBQLJPQL
NPE
Thursday, December 8, 11
Thursday, December 8, 11
Mas escala né?!
Thursday, December 8, 11
JVM
Scala ClojureJython
DynJSRhino Groovy
Thursday, December 8, 11
RubyMais expressiva que Java
class Beer attr_accessor :beer_id, :description, :created_at end
Thursday, December 8, 11
DRY
“It is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail.” - Abraham Maslow
Thursday, December 8, 11
JRubyJava + Ruby
Thursday, December 8, 11
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
Thursday, December 8, 11
“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
Thursday, December 8, 11
Server Side
Thursday, December 8, 11
Ruby AppRails
Rack
Sinatra
Apache/Nginx
Passenger/Thin
Thursday, December 8, 11
Rails
Rack
Sinatra
Apache/Nginx
Passenger/Thin
crond
Jobs
Ruby App
Thursday, December 8, 11
Rails
Rack
Sinatra
Apache/Nginx
Passenger/Thin
crond
JobsResque/
DelayedJob
Tasks
Ruby App
Thursday, December 8, 11
Rails
Rack
Sinatra
Apache/Nginx
Passenger/Thin
crond
JobsResque/
DelayedJob
Tasks
god/monit
Daemons
Ruby App
Thursday, December 8, 11
JBossTomcat
Thursday, December 8, 11
JBossHornetQ
Thursday, December 8, 11
JBossQuartz
Thursday, December 8, 11
JBossClustering
Thursday, December 8, 11
AS 7Redução do footprint de memória
Class loader modularQueda no tempo de startup
EE6 compliant
Thursday, December 8, 11
TorqueBox“The power of JBoss with the
expressiveness of Ruby”Jim Crossley - MagicRuby Conference
Thursday, December 8, 11
TorqueBox
Thursday, December 8, 11
InstalaçãoTorqueBox do zero
Thursday, December 8, 11
Pré-requisitos➜ java -versionjava version "1.6.0_07"Java(TM) SE Runtime Environment (build 1.6.0_07-b06-153)Java HotSpot(TM) 64-Bit Server VM (build 1.6.0_07-b06-57, mixed mode)
Thursday, December 8, 11
➜ jruby -S gem install torquebox torquebox-capistrano-support
Thursday, December 8, 11
➜ wget http://repository-torquebox.forge.cloudbees.com/release/org/torquebox/torquebox-dist/2.0.0.beta1/torquebox-dist-2.0.0.beta1-bin.zip➜ unzip torquebox-dist-2.0.0.beta1-bin.zip
➜ export TORQUEBOX_HOME=$PWD/torquebox-dist-2.0.0.beta1➜ export JBOSS_HOME=$TORQUEBOX_HOME/jboss➜ export JRUBY_HOME=$TORQUEBOX_HOME/jruby
➜ export PATH=$JRUBY_HOME/bin:$PATH
Thursday, December 8, 11
Rails rails new beer -m $TORQUEBOX_HOME/share/rails/template.rb
Thursday, December 8, 11
EstruturaDiretórios do TorqueBox
Thursday, December 8, 11
Rake tasksrake torquebox:deployrake torquebox:undeployrake torquebox:run
Thursday, December 8, 11
DeploymentMake knobs, not WAR!
Thursday, December 8, 11
beer-knob.yml application: root: /Users/Bruno/javaonebrasil/beer environment: development
Thursday, December 8, 11
Thursday, December 8, 11
Aplicação
Thursday, December 8, 11
Gemfile
source "http://torquebox.org/2x/builds/584/gem-repo" 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.x.incremental.584" gem "torquebox", "2.x.incremental.584"
Thursday, December 8, 11
WebRack, Sinatra, Rails
Thursday, December 8, 11
Cachingclass BeersController < ApplicationController caches_action :most_popular, :expires_in => 30.seconds def most_popular @popular_beers = Beer.most_popular(:limit => 25) end end
Thursday, December 8, 11
Thursday, December 8, 11
Clustering➜ torquebox run --clustered
Thursday, December 8, 11
class TorqueBoxCommand < Thor TASK_ORDER = %w(deploy undeploy start cli env help) map "run" => "start" desc "run", "Run TorqueBox" method_option :clustered, :type => :boolean, :desc => "Run TorqueBox in clustered mode" def start setup_environment TorqueBox::DeployUtils.run_server(:clustered => options.clustered, :max_threads => options['max-threads'], :bind_address => options['bind-address']) endend
Internals
Thursday, December 8, 11
Cache distribuído!
Thursday, December 8, 11
mod_clusterhttpd-based load balancer
Thursday, December 8, 11
InfinispanCaching
Thursday, December 8, 11
InvalidationCache
Server1Cache
Server2
Thursday, December 8, 11
InvalidationCache
Server1Cache
Server2
NEW
Notificação
CacheDesatualizado
Thursday, December 8, 11
../config/application.rbmodule Beer class Application < Rails::Application config.cache_store = :torque_box_store end end
Thursday, December 8, 11
ReplicatedCache
Server1
CacheServer2
CacheServer2
CacheServer2
Sync
Sync
Thursday, December 8, 11
../config/application.rbmodule Beer class Application < Rails::Application config.cache_store = :torque_box_store, {:mode => replicated, :sync =>false} end end
Thursday, December 8, 11
SchedulingAgendamento de Jobs
Thursday, December 8, 11
Internalspublic class RubyJobProxy implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { Ruby ruby = null; try { ruby = this.runtimePool.borrowRuntime( resolver.getComponentName() ); JobComponent job = (JobComponent)resolver.resolve( ruby ); job.run(); } catch (Exception e) { throw new JobExecutionException( e ); } finally { if (ruby != null) { this.runtimePool.returnRuntime( ruby ); } } }
Thursday, December 8, 11
Internalspublic class RubyJobProxy implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { Ruby ruby = null; try { ruby = this.runtimePool.borrowRuntime( resolver.getComponentName() ); JobComponent job = (JobComponent)resolver.resolve( ruby ); job.run(); } catch (Exception e) { throw new JobExecutionException( e ); } finally { if (ruby != null) { this.runtimePool.returnRuntime( ruby ); } } }
Thursday, December 8, 11
../app/jobsclass JobDemo def initialize #Codigo de inicializacao end def run # O que você quer executar end end
Thursday, December 8, 11
../config/torquebox.ymljobs: sync_agenda: job: JobDemo cron: '0 0 12 * * ?'end
Thursday, December 8, 11
MensageriaJava Messaging Service + HornetQ
Thursday, December 8, 11
O Ministério da Saúde adverte:
NOSQL COMO MENSAGERIA PODE
TRAZER DANOS A SUA SAÚDE E A DE SEUS FAMILIARES
Thursday, December 8, 11
RAILS APP
GreenfieldREST + NoSQL
SINATRA APP
Request/Responsext
pub/sub
NoSQL
Thursday, December 8, 11
RAILS APP
Real WorldNobody Cares!
MAINFRAME
Request/Responsext
pub/sub
NoSQL
Thursday, December 8, 11
../config/torquebox.yml/topics/beerTopic/queues/queueBeer:
Thursday, December 8, 11
Tasksclass EmailerTask < TorqueBox::Messaging::Task def send_welcome(payload) to = "#{payload[:name]} <#{payload[:address]}>" # send welcome email to the user end end
Thursday, December 8, 11
Tasksclass UserController < ApplicationController def register user = User.new(params[:user]) EmailerTask.async(:send_welcome, :address => user.email, :name => user.name) end end
Thursday, December 8, 11
Processorsinclude TorqueBox::Messaging class PrintHandler < MessageProcessor def on_message(body) puts "Processing #{body} of #{message}" end def configure(opts) @color = opts['color'] end end
Thursday, December 8, 11
Queuesinclude 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
Thursday, December 8, 11
Future
Thursday, December 8, 11
class EmailerTask def send_welcome(payload) to = "#{payload[:name]} <#{payload[:address]}>" # long running task end end
Future
Thursday, December 8, 11
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
Thursday, December 8, 11
future = @emailTask.send_welcome(:send_welcome)
future.started? future.complete? future.error?
future.resultfuture.result(10000)
Future
Thursday, December 8, 11
Services
Thursday, December 8, 11
class BeerService def initialize @queue = Messaging::Queue.new(“beer”) end def start @queue.publish “Testing” end def stop # O que fazer quando o serviço receber um stop end end
Services
Thursday, December 8, 11
Singleton Services
Server1 Server2
Clustered
BeerService BeerService
Thursday, December 8, 11
Singleton Services
Server1 Server2
Clustered
BeerService BeerService
Thursday, December 8, 11
Services➜ torquebox run --clustered
../config/torquebox.ymlservices: BeerService: singleton: true end
Thursday, December 8, 11
CDIInjeção de dependências
Thursday, December 8, 11
Pra quê?
Thursday, December 8, 11
Javapackage br.com.javaonebrasil;
public class Beer { //gets e sets public void say(String message) { // Execução do método }}
Deploy do jar na aplicaçãoapp/models/views/controllers/lib/beer.jar
Thursday, December 8, 11
Rubyclass BeerController < ApplicationController
include TorqueBox::Injectors
def create beer = inject(br.com.javaonebrasil.Beer ) beer.say “Ruby is for Java” end
end
Thursday, December 8, 11
JNDIclass MyService include TorqueBox::Injectors def initialize opts={} @factory = inject("java:comp/env/jdbc/myDB") end end
Thursday, December 8, 11
Destinationsclass MyService include TorqueBox::Injectors def initialize opts={} @inbound = inject("/topic/beerpub") @outbound = inject("/queue/beer") end end
Thursday, December 8, 11
Transactions
Rails Application
Queue Database Infinispan
Topic
XA Distributed, multi resource transaction
Thursday, December 8, 11
XA (2PC)HornetQ ✔
TorqueBox + ActiveRecord ✔Infinispan ✔
Thursday, December 8, 11
Outras featuresAutenticação + Websockets
Thursday, December 8, 11
BackStage
Thursday, December 8, 11
Stomp BoxTorqueBox deployment support
Thursday, December 8, 11
Thursday, December 8, 11
What’s next?
Thursday, December 8, 11
Polyglot
QueueQueue
Immutant
TorqueBox
Thursday, December 8, 11
Getting started
Installing TorqueBox 2.0 http://vimeo.com/33299335
Thursday, December 8, 11
Comunidade
irc.freenode.net #torquebox http://torquebox.orghttp://github.com/torqueboxtwitter: @torquebox
Thursday, December 8, 11
Creative Commons BY-SA 3.0
Obrigado!@abstractj
http://github.com/abstractj
Thursday, December 8, 11