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 :-)