TorqueBox - When Java meets Ruby

Post on 09-May-2015

1.748 views 1 download

Transcript of TorqueBox - When Java meets Ruby

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