Friday, March 23, 2007

JMS in Ruby using Stomp

I have been looking for ways to build asynchronous message driven systems in Ruby for a while, rinda works well, but it's nice to tap into the whole JMS universe, so I just gave a try to stomp,
http://stomp.codehaus.org/Ruby+Client
IMO last missing piece in the ruby ecosystem. Sending text messages via Apache Activemq works great, here are the steps:

1. download activemq
http://activemq.apache.org/activemq-411-release.html
and run
C:\java\apache-activemq-4.1.0-incubator\bin>activemq.bat

2. go to new command line and type
gem install stomp

3. type up following 2 apps from http://svn.codehaus.org/stomp/ruby/trunk/bin/ :
send.rb:
# Copyright 2006 LogicBlaze Inc.
begin; require 'rubygems'; rescue; end
require 'stomp
begin
@port = 61613
@host = "localhost"
@user = ENV["STOMP_USER"];
@password = ENV["STOMP_PASSWORD"]
@host = ENV["STOMP_HOST"] if ENV["STOMP_HOST"] != nil
@port = ENV["STOMP_PORT"] if ENV["STOMP_PORT"] != nil
@destination = "/topic/default"
@destination = $*[0] if $*[0] != nil
$stderr.print "Connecting to stomp://#{@host}:#{@port} as #{@user}\n"
@conn = Stomp::Connection.open @user, @password, @host, @port, true
$stderr.print "Sending input to #{@destination}\n"
@headers = {'persistent'=>'false'}
@headers['reply-to'] = $*[1] if $*[1] != nil
STDIN.each_line { |line|
@conn.send @destination, line, @headers
}
rescue
end


cat.rb:
# Copyright 2006 LogicBlaze Inc.
begin; require 'rubygems'; rescue; end
require 'stomp'
begin

@port = 61613
@host = "localhost"
@user = ENV["STOMP_USER"];
@password = ENV["STOMP_PASSWORD"]

@host = ENV["STOMP_HOST"] if ENV["STOMP_HOST"] != nil
@port = ENV["STOMP_PORT"] if ENV["STOMP_PORT"] != nil

@destination = "/topic/default"
@destination = $*[0] if $*[0] != nil

$stderr.print "Connecting to stomp://#{@host}:#{@port} as #{@user}\n"
@conn = Stomp::Connection.open @user, @password, @host, @port, true
$stderr.print "Getting output from #{@destination}\n"

@conn.subscribe @destination, { :ack =>"client" }
while true
@msg = @conn.receive
$stdout.print @msg.body
$stdout.flush
@conn.ack @msg.headers["message-id"]
end

rescue
end


4. Open second console and run
ruby cat.rb

5. ruby send.rb

6. Type up messages and see them arrive, that was easy!!!