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

Comments are closed.