logo

First Experiences with Grails, JMS and OpenMQ

logo

I’ve just finished converting groovyblogs over to a (largely) message driven architecture. I’m a bit of an JMS noob, but the adventure has been fantastic, and it’s time to write some stuff down. The reason I’m even interested in a messaging is for the acquisition of feed xml and thumbnails. I presently do the former in-process in the app server, and the later via Groovy XML-RPC to a Thumbnail Server running locally.

My re-design involves creating four queues: urlRequest, urlResponse, thumbnailRequest, thumbnailResponse. The webapp will put the requests on the request queues, then an external process will deliver source the the thumbnails and feed data (external to the app server) and deliver them on the response queues. All the db action remains in the webapp, so all my hibernate/GORM goodness can continue as usual.

Holy Queue Admin tool, batman!

First off was choosing an MQ provider. ActiveMQ seems to have all the mindshare, and was easy to install, but I had quite a bit of trouble actually getting it working correctly. My clients would frequently drop their connections, messages were undelivered since I terminate JmsTemplate connections incorrectly, messages were not delivered on reconnect, and it was generally unforgiving to my JMS noob-ness. I’m sure it’s not ActiveMQ’s fault. But it wasn’t a great experience for me. YMMV.

Then I found out that OpenMQ ships embedded right into Glassfish, so I made the switch and have been happy every since. When I’m running outside of the container (“grails run-app”), I just run a standalone copy of OpenMQ to test against, and when I deploy to Glassfish, I just use the embedded one. Sensational! OpenMQ ships with a funky Swing admin tool (pictured above), but the only thing it didn’t have was a funky Queue content browser (like the Web one that ships with ActiveMQ, but I setup Hermes-JMS and now I can happily browse the contents of both local and remote queue.).

Ok. I had my JMS platform, now it was just a matter of getting the data into and out of those queues. Enter the JMS Plugin. This plugin rocks so hard! Define a service that has an expose = ['jms'] and life will be good for you. To listen on the queue, just define an onMessage closure. You can use naming conventions to map to existing queue names, but in my case I had specific ideas on what I wanted the queue to be called, so I set an explicit ‘destination’:

class ThumbnailQueueService {

    static expose = ['jms']

    static destination = "thumbnailResponse"

    def onMessage = {msg ->
        println "Got Thumbnail Response: ${msg.url}"
    }
}

All the messages I pass around are normal java.util.Map objects, which makes it easy to ship a bunch of payload at once. Once that’s done, anything that ends up on the thumbnailResponse queue will get automatically passed to my onMessage routine. Awesome! But what about putting the thumbnail request on the queue? It’s a snack:

def sendRequest(BlogEntry be, String smallFilename, String bigFilename) {

        try {
            sendJMSMessage("thumbnailRequest",
              [ id: be.id,
                url : be.link ])
        } catch (Exception e) {
             log.error("Failed to send MQ request for ${be?.link}", e)
        }

    }

All services get a “sendJMSMessage” routine injected for free. Just need to pass the name of the queue as the first arg, and your payload for the Queue as your second, and you’re in business!

The only thing left was configuring up my JMS connection factory. I needed to drag two jars from OpenMQ and put them into my lib directory for standalone testing (imq.jar and jms.jar). After that, just a matter of editing /conf/spring/resources.groovy to define my local OpenMQ connection factory class. I suspect I should really acquire this connection factory via JNDI (if you know about such things please comment), but here’s the config at the moment:

import com.sun.messaging.*

beans = {

    connectionFactory(ConnectionFactory) {
        // defaults to localhost, so nothing to configure
    }
}

And we’re done. One JMS-powered groovyblogs ready for local testing. Fire up OpenMQ with a “/opt/openmq-4.1/bin/imqbrokerd -tty” so you can see who’s connecting, and start filling those queues.

But how are we going to get those messages off the queue so we can actually generate the thumbnail? We’ll leave that to the next installment, when we venture into GMaven and Spring Message Driven POJOs (or POGOs in my case :-)

14 Responses to “First Experiences with Grails, JMS and OpenMQ”

  1. Sakuraba says:

    As inspiring as always.

    Great work!

  2. Bob herrmann says:

    Thanks for posting this!

  3. Zack says:

    Great post Glen.

    What drove you to make the switch to a message driven architecture?

  4. Glen Smith says:

    @Zack. The thumbnail generate process uses SWT and makes a bunch of native calls to create a new “real” browser window.

    I didn’t want that native stuff happening in the app server process space for fear of segfaults, so I’ve been using XMLRPC to a thumbnail service on the same box running as a standalone groovy app. But it’s obviously a very slow and blocking call… so threads are tied up in the process.

    Moving to a Queue model decouples all of that action. Need a thumbnail generated? Stick a request on the queue (which only takes a millisecond). When things are done it will post one back and you can update the file system on the web server. Very tidy, fast, and fault tolerant.

  5. Alan says:

    I’m covering the same ground, so good to see the plugin working elsewhere. On a side note, I subscribe to the podcast, so it’s great to put a face to the voice! Keep it up :)

  6. Hi Glenn! I scheduled a spotlight on your blog for tomorrow morning (US Pacific Time) [1]. Thanks for the great writeup. – eduard/o

    [1]http://blogs.sun.com/theaquarium/entry/openmq_with_grails_glassfish_and

  7. Wesley says:

    Great Post!
    Could you give me some hints on config HermesJMS with OpenMQ?

    Thanks!

  8. I had to add another import

    import java.jms.*

    to the resouces.groovy as well…

  9. I also wanted to test the automatic reconnect feature so I’ve spent some time trying to understand how this could be configured for OpenMQ and Grails and this JMS plugin. OpenMQ docs only refer to the administered objects of OpenMQ, which I think is only leveraged via JNDI and quite complicated to set up…

    If you want to try a simple automatic reconnect without JNDI I managed to come up with the following resources.groovy

    import com.sun.messaging.*
    import java.jms.*

    beans = {

    connectionFactory(ConnectionFactory) {

    //Original source http://forum.springframework.org/showthread.php?t=40471
    this.setProperty(ConnectionConfiguration.imqAddressList, “localhost”);
    this.setProperty(ConnectionConfiguration.imqReconnectEnabled, “true”);
    this.setProperty(ConnectionConfiguration.imqReconnectAttempts, “10″);

    }
    }

  10. Glen Smith says:

    Awesome work @Anders.

    Very cool how you’ve used the Spring Bean Builder DSL to get around the need for a custom FactoryBean to set those properties. I’ve never thought of that!

  11. James says:

    Great post – put me on to Hermes JMS as a GUI.

    Can I second Wesley’s request for some more information on how you are accessing OpenMQ through Hermes?

  12. Osvaldo says:

    Great !!

  13. Greg Harrison says:

    Great stuff.

    OpenMQ – i’m starting with it and having real trouble configuring retries and a retry interval for messages. By this i mean redelivery [n] times before sending to the DMQ. I have had no luck after days of searching and attempting to get it work. I’m using Spring and cant see any way of configuring these properties. Did you use redelivery, and a redilivery interval in your application?

  14. Jacky Wong says:

    I tried follow your example with the following setup:
    Grail 1.2.2
    OpenMQ 4.4.1
    JMS Plugin 0.5.1

    However, my service class could not receive the message.

    After some tracing on the plugin’s source code, I found that no JMS Listener has been registered for my service class method as my “onMessage” method become “getOnMessage” method when the plugin is inspecting my service class.

    The issue is gone after I changed the method syntax as following:
    def onMessage(msg) { // Originally is def onMessage = {msg ->
    println “Got Thumbnail Response: ${msg.url}”
    }

    Not sure if this is a grails bug or the plugin’s bug

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

logo
logo
Powered by WordPress | Designed by Elegant Themes