Integrating Rails and ActiveMQ with ActiveMessaging/REST
ActiveMQ ships with a simple chat demo. The chat demo uses a Servlet to relay AJAX requests to and from a JMS Topic (the source for this application is also a good place to start if you are interested in learning about Jetty Continuations). Below are some instructions on how to build an alternate client with Rails for the chat demo. This is done via activemessaging(AKA a13g), a plugin which relays/dispatches the messages to the Servlet (or any other “broker”).
Assuming Java, Ruby and Rails …
$rails -v
Rails 1.2.3
$ruby -v
ruby 1.8.5
$java -version
java version "1.6.0_01"
Setting Up ActiveMQ
Download and unzip the binary. Start the broker and demo application by running /apache-activemq-5.0-SNAPSHOT/bin/activemq . This only works with a 20070623 (or later) build of ActiveMQ. For an earlier build, see this patch.
Create a Rails application
$rails a13g
(output excluded)
Generate a Controller and a View
$cd a13g
$script/generate controller talk index
exists app/controllers/
exists app/helpers/
create app/views/talk
exists test/functional/
create app/controllers/talk_controller.rb
create test/functional/talk_controller_test.rb
create app/helpers/talk_helper.rb
create app/views/talk/index.rhtml
Make a13g/app/controllers/talk_controller.rb look like this:
class TalkController < ApplicationController
include ActiveMessaging::MessageSender
publishes_to :chat_client
def new
@message = params[:message]
publish :chat_client, @message
render :action => 'index'
end
end
Make a13g/app/views/talk/index.rhtml look like this:
<%= start_form_tag :action => 'new' %>
<%=text_field_tag :message %>
<%= submit_tag “submit” %>
<%= end_form_tag %>
Install the a13g plugin and it’s dependencies
$script/plugin install http://activemessaging.googlecode.com/
svn/trunk/plugins/activemessaging
(output excluded)
$gem install daemons
(output excluded)
$gem install stomp
(output excluded)
Create a Processor
$script/generate processor ChatClient
create app/processors
create app/processors/chat_client_processor.rb
create test/functional/chat_client_processor_test.rb
create config/messaging.rb
create config/broker.yml
create app/processors/application.rb
create script/poller
An a13g Processor is similar to a MessageConsumer. Make the a13g/app/processors/chat_client_processor.rb look like this:
class ChatClientProcessor < ApplicationProcessor
subscribes_to :chat_client
def on_message(message)
logger.debug "ChatClientProcessor received: " + message.to_s
end
end
Configuring a13g
Destinations are mapped to symbols using messaging.rb (BTW, a13g committers - if you are reading this, please consider changing Gateway.queue to Gateway.destination, for reasons demonstrated in this post ). Make a13g/config/messaging.rb look like this:
ActiveMessaging::Gateway.define do |s|
s.queue :chat_client, 'topic://CHAT.DEMO'
end
Copy this a13g adapter to a13g/vendor/plugins/activemessaging/
lib/activemessaging/adapters/rest.rb .
Tell a13g to use the adapter by making a13g/config/broker.yml look like this:
development:
adapter: rest
port: 8161
app: "/demo/amq"
host: localhost
Start Rails and a13g
$script/server
(output excluded)
$script/poller run
(output excluded)
Subscribing to topic://CHAT.DEMO (processed by ChatClientProcessor)
Subscribed to topic://CHAT.DEMO, using session id of 1swb9sf6yi1ke
The rest adapter establishes an HTTP session. The session id will be used for all subsequent communication (publishing and consuming).
Let’s Chat
In your browser go to the chat demo and start a conversation.

Looking at the console for the activemessaging poller process, we can see that this message was received by the ChatClientProcessor.
$script/poller run
(output excluded)
Subscribing to topic://CHAT.DEMO (processed by ChatClientProcessor)
Subscribed to topic://CHAT.DEMO, using session id of 1swb9sf6yi1ke
ChatClientProcessor received: I was thinking ... one day,
they are going to standardize DSLs
By pointing a different browser window (different cookie/session) we can start an argument via the talk view.

Back in the original browser, we can see that chat messages are dispatched both ways.

The chat continues …

From the poller console …
ChatClientProcessor received: I was thinking ... one day, they are going to standardize DSLs ChatClientProcessor received: No way. Never. ChatClientProcessor received: Think about it. ChatClientProcessor received: Large conservative orgs will not be open to it. ChatClientProcessor received: True. ChatClientProcessor received: And the only way they will adopt DSLs is to go industry wide. ChatClientProcessor received: Think JCP, WS-* ... only for *each* industry .... ChatClientProcessor received: Accounting, Finance, Logistics, etc. ChatClientProcessor received: Interesting