Feb 11

Server push with Ruby on Rails using Flex, JRuby, and BlazeDS

Tag: ActiveMQ, ActiveMessaging, Flex, Flex and Rails, JRuby, Messaging, Server Push, blazedsDerek Wischusen @ 5:32 am

In a previous post I discussed how you can integrate Flex and Scala/Lift using BlazeDS.  In this post I’ll show that it’s also possible to get Rails running on BlazeDS using JRuby.

Here is what I am using for this example:

You don’t really need Netbeans, but I’ve found that it makes things a bit easier.

For this example I am going to assume you have a basic understanding of Flex and Rails.  That said, if anyone has a question, not matter how basic, please feel free to ask.

Here are the source files if you want to follow along:

—– 

Ok, first lets get the Rails app set up.

1. Create a new Rails app called RoRBlaze.

2. Generate a controller called Greeting with an index view.  i.e.,

> ruby script/generate controller Greeting index

3.  Open up your newly generated greeting.rb file and add the following code:

class GreetingController < ApplicationController
  include Java
  import "flex.messaging.MessageBroker"
  import "flex.messaging.messages.AsyncMessage"
  import "flex.messaging.util.UUIDUtils"

  @@msgBroker = MessageBroker.getMessageBroker(nil)
  @@clientID = UUIDUtils.createUUID()

  def hello
    @msg = AsyncMessage.new()
    @msg.setDestination("notifications")
    @msg.setClientId(@@clientID)
    @msg.setMessageId(UUIDUtils.createUUID())
    @msg.setTimestamp(Time.new.to_f)
    @msg.setBody("Hello from Rails")
    @@msgBroker.routeMessageToService(@msg, nil)
    render :text => "Greeting Sent"
  end
end

4. Open view/greeting/index.rhtml and add a button to it like so,

<%=button_to "Send Greeting to Flex", :action=>"hello" %>

5. Go to the BlazeDS folder and  locate the following two .jar files in tomcat\webapps\blazeds\WEB-INF\lib:

  • flex-messaging-common.jar
  • flex-messaging-core.jar

6. Copy these .jar files into the lib folder in your Rails app (keep this folder open, you’ll need the more of the .jars in a moment).

7. In your Rails app open up config/environment.rb and add the following to the bottom of the file:

Dir["#{RAILS_ROOT}/lib/**/*.jar"].each do |jar|
  require jar
end

Alright, thats pretty much all of the Ruby code for this simple example.  Now we need to use the Goldspike Rails plugin to modify our Rails app so that it can run in a Java server (like Tomcat or Jetty or Glassfish, etc)

8.  From a command line, go to the root of your Rails app and install the Goldspike plugin:

> ruby script/plugin install http://jruby-extras.rubyforge.org/svn/trunk/rails-integration/plugins/goldspike

9. WARify you Rails app using the following rake command:

> rake war:standalone:create

Assuming that Goldspike did its job, you should now have a folder called WEB-INF in the root of you Rails app.  We need to add a few file to this folder to get BlazeDS working.

10. Copy the .jars from BlazeDS\tomcat\webapps\blazeds\WEB-INF\lib into RoRBlaze\WEB-INF\lib

11. Copy the folder BlazeDS\tomcat\webapps\blazeds\WEB-INF\flex into RoRBlaze\WEB-INF

12. Open up the web.xml file in blazeds\WEB-INF and merges its contents into the web.xml file in RoRBlaze\WEB-INF.  Click here to see what the final file should look like.

13. Open up RoRBlaze\WEB-INF\flex\messaging-config.xml and modify it so that it looks like this (click to view the file).  The key thing to note here is that we added a messaging destination called “notifications”.  This is the destination that the Greeting controller publishes to and it is the destination that our Flex app will subscribe to.

14. Open up RoRBlaze\WEB-INF\flex\services-config.xml and modify it so that it looks like this (click to view the file).  The key thing to notice in this file is that we defined a streaming channel called my-streaming-amf that BlazeDS will use to push messages over a persistent, streaming HTTP channel.

That’s it for the Rails app.  Now let’s create the Flex app.

—–

1. Create a new Flex Project (File -> New -> Flex Project)

2. Fill in the rest as follows:

  • Project name: RoRBlaze
  • Application type: Web Application
  • Application server type: J2EE
  • Use remote object access service: check this
  • Root folder: RoRBlaze  (the root folder of your Rails app)
  • Root URL: http://localhost:8080/RoRBlaze/
  • Context root: /RoRBlaze
  • Output folder: RoRBlaze\public
  • Output folder URL: http://localhost:8080/RoRBlaze

3. Open up RoRBlaze.mxml and edit it like so:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
	xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="vertical"
	creationComplete="consumer.subscribe()">

    <mx:Script>
        <![CDATA[
          	import mx.messaging.events.MessageEvent;

            private function messageHandler(message: MessageEvent): void
            {
                pushedMessage.text = message.message.body as String;
            }
        ]]>
    </mx:Script>

    <mx:Consumer
    	id="consumer"
    	destination="notifications"
    	message="messageHandler(event)"
    	channelConnect="trace(event)"
        channelFault="trace(event)"
        fault="trace(event)" />

    <mx:TextInput id="pushedMessage" width="300"/>
</mx:Application>

That’s it for the Flex app.  Let’s test everything out.

—–

1. Open a terminal and go to the root of your Rails app.  Then use Goldspike to boot up your Rails app in a Jetty server:

> rake war:standalone:run

In a few short seconds your Rails app should  be up and running.

2. Launch the Flex app.

3.  Open a browser and enter the following URL: http://localhost:8080/RoRBlaze/greeting

You should see a single button that says “Send Greeting to Flex”

4. Click the button.

Upon clicking the button you should see the browser display “Greeting Sent” and you should see “Hello from Rails” appear in the text input in your Flex app.

That’s it.  Assuming that everything worked properly, the Rails app should have pushed an AMF encoded message to Flex using a persistent streaming HTTP channel created by BlazeDS.

One importatant thing to take note off is that this technique could be useful to you even if you aren’t planning on using Flex/Flash as your presentation layer.  You could use a Juggernaut style approach and push messages from Rails to an embedded Flash player whose only job is to pass those messages along to the browser.

This example demonstrates a very simple way to integrate Flex, Rails, and BlazeDS.  I think the ideal way to integrate these technologies would be to use the ActiveMessaging plugin for Rails, since both ActiveMessaging and BlazeDS have JMS adapters which they could use to integrate with a more robust messaging system like ActiveMQ.  If I can find some time in the near future, and if there is any interest, I’ll do a follow up post on this.

17 Responses to “Server push with Ruby on Rails using Flex, JRuby, and BlazeDS”

  1. Brian says:

    I’d love to see a follow up post. I’d also love to see a way how maybe this could run on its own and then just have rails connect to it rather than putting lots of java config stuff into the rails project.

  2. Vixiom Axioms » Interesting Links: Rails and BlazeDS, Yahoo! map components for AS3 says:

    [...] Derek shows how to push AMF encoded messages from the server with Rails through BlazeDS. [...]

  3. phil swenson says:

    Great post!

    My issue with this is you have to deploy to a war file and copy to your java web server to test this code… one of the great things about RoR is that you can just tweak code and hit refresh.

    Has anyone thought about how to set this up so you don’t have to war and deploy every time you make a tweak (for development purposes only)???

  4. Derek Wischusen says:

    @Brian – Yeah, there are a lot of XML files, but once you have them set up for one project you can pretty much reuse them as is for future projects.

  5. Derek Wischusen says:

    @Phil –

    If you run the app using war:standalone:run the it will be run directly in a Jetty server. You don’t need to take the .war file and deploy it each time (that would become extremely tedious). I just did some quick tests and you can modify your controllers while the app is running and see the changes without having to restart the server.

  6. phil swenson says:

    I tried this out and verified that running the rails app standalone would let you tweak the files w/o rebuilding the war, which is sweet.

    However I always got a nil from this line: @@msgBroker = MessageBroker.getMessageBroker(nil) in the rails controller. I had visibility to the MessageBroker class (I could do a MessageBroker.methods), but it always returned a nil.

    I then downloaded your code and noticed you are on rails 1.2, I’m on 2.0. I don’t know if that matters. I tried your source directly as well and got the same behavior.

    Any ideas on this?

    Also, I notice that changing the logging level to debug in web.xml doesn’t show any of the blazeds messages.

  7. Daniel Rails with Netbeans says:

    Hey Derek,
    well done! Hello from Rails worked! Thanks and I hope to see further posts by you.

    Greets,
    Daniel

  8. Haluk Durmus says:

    I tried to compile the mxml file with the open source mxcl compiler using following options:
    -use-network -compiler.context-root=/RoRBlaze

    but the flash file couldn’t access the consumer.
    I think there should be some other comand line options I have to set …

    No problem from Windows Flexbuilder (co workers pc).
    But I don’t want to switch from one ide to and other and also only use linux for developing.

  9. Haluk Durmus says:

    Found the required option :) for mxmlc:
    -services /RoRBlaze/WEB-INF/flex/services-config.xml

  10. Andre’s Blog » Blog Archive » links for 2008-03-04 says:

    [...] flexonrails.net » Server push with Ruby on Rails using Flex, JRuby, and BlazeDS it’s possible to get Rails running on BlazeDS using JRuby. (tags: flex BlazeDS jruby rails ruby java flash) [...]

  11. Ajay says:

    I want to develop the whiteboard using flex and RoR,I need key start in order to do this.

  12. Derrek says:

    Is it possible to configure it to run over any port e.g. port 80?
    - Thanks

  13. Siva Prasanna Kumar says:

    Nice Article, But I feel this isn’t 100% complete since, lets say the push delay is higher and clients starting after the initial data push have to wait till the next push to happen for updating them self, I have explained this scenario and also have provided a Java Based solution combining the “Service Adapter” and “Message Broker” Check

    http://soa2world.blogspot.com/2008/07/server-push-data-push-in-flex-using.html

    Thanks,

    Siva Prasanna Kumar .P

  14. Andre says:

    Very good article!! But what about the normal way, making remote calls from flex? Can Rails controllers act as remote objects by specifing them in the remote_config.xml as it is normally done with java classes. Or is there a possibility to call active_records methods from java classes.

  15. Alexis Tejeda says:

    Great, just great, very nice to found info like this here… cheers !.

  16. alex says:

    i’ve been working in this using warble and rails 2.3.2 (with jruby), but i have an issue in the message broker servlet, i cant get this message broker servlet work, so if can u really help, thanks, or update the tutorial, thanks in advance.

  17. Richard Jones says:

    You might want to check out StreamHub – its a push server written in Java. I can stream to different languages:

    http://www.stream-hub.com/

    Thanks,
    Richard.

Leave a Reply