Led & Sustained by

G2one Logo

Developed with

Intellij

Powered by

Spring

JMS Plugin

JMS Plugin

This plugin allows you to expose your Service artifacts as Message-Driven POJOs/POGOs using Spring's JMS support, described http://www.springframework.org/docs/reference/jms.html. This enables your Services to receive messages from a JMS broker without implementing any special interfaces. As of version 0.2, the plugin also enables the easy sending of JMS messages from Grails Controllers and Services.

Note The plugin only works with Grails 0.6 and above.

Setup

1.1 Install the plugin

grails install-plugin jms

1.2 Creating a Connection Factory

The use of the JMS Plugin requires that you have a bean named connectionFactory defined in grails-app/conf/spring/resources.xml. See your broker's documentation for instructions for how to do this. For example, using ActiveMQ's default configuration:

<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="tcp://localhost:61616" />
</bean>

Usage

2.1 Exposing your Service

To expose your service as an MDP, you need to create a message listener closure or method. By default, this needs to be called onMessage, although you can override this as we'll see below. Once you've defined your message listener, simply add a static property called expose and set it to a list containing 'jms'. For example:

class SampleQueueService {
    static expose = ['jms']

    def onMessage = {
       println "GOT MESSAGE: $it"
    }

}

If you define onMessage as a method, that'll work too:

class SampleQueueService {
    static expose = ['jms']

    def onMessage(messageObject) {
       println "GOT MESSAGE: $messageObject"
    }

}

By default, this will attach this service as a message listener to a JMS Queue named sampleQueue

XFire/Remoting Compatibility

You may notice that the configuration is similar to that for the XFire and Remoting plugin.

2.2 Additional Configuration

There are a number of configuration changes you can make by setting various static properties on your service class:

static listenerCount = 5 Spawns 5 threads to listen for messages defaults to 1
static destination = "OtherQueueName" Sets an alternate destination name defaults to Service's property name
static listenerMethod = "handleMessage" Sets an alternate listener method (or closure) name

defaults to "onMessage"

static pubSub = true Tells the Spring JMS classes to use Topic instead of Queue defaults to false
static messageSelector = "MessageType = 'DATA'" Associates JMS Message Selector to the listener defaults to null
static durable = true Creates a durable subscription (applies to Topics only) defaults to false
static clientId = "myclient" Provides a client identifier for durable subscriptions. defaults to "grailsAppListener", id property can be used instead of clientId for backwards compatibility

3 Sending JMS Messages

As of version 0.2 of the plugin, Service and Controller artefacts have these closures defined:

  • sendQueueJMSMessage & sendJMSMessage - send messages to a Queue destination
  • sendJMSMessage & sendPubSubJMSMessage - send messages to a Topic destination

    All closures take two parameters: the destination name and the message. For example, here's a save action closure that sends a JMS message upon entity creation:
    def save = {
        def blogEntry = new BlogEntry(params)
        if(!blogEntry.hasErrors() && blogEntry.save()) {
            flash.message = "BlogEntry ${blogEntry.id} created"
            sendJMSMessage("sample", "Blog Entry entitled ${blogEntry.title} has been created.")
            redirect(action:show,id:blogEntry.id)
        }
        else {
            render(view:'create',model:[blogEntry:blogEntry])
        }
    }

Configuration Examples

Here are some specific sample configurations.

Active MQ

  1. Download ActiveMQ from http://activemq.apache.org/
  2. Add activemq-core-4.1.1.jar, backport-util-concurrent-3.0.jar, geronimo-j2ee-management_1.0_spec-1.0.jar, and geronimo-jms_1.1_spec-1.0.jar from the ActiveMQ distribution into the lib directory of your Grails application.
  3. Add this to your conf/spring/resources.xml changing the brokerURL based on your ActiveMQ configuration:
    <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61616"/>
    </bean>
  4. Start ActiveMQ

JBossMQ (running inside JBossAS)

This applies to Grails applications deployed inside JBossAS.

  1. Download JBossAS from http://labs.jboss.com/jbossas/
  2. Add this to your conf/spring/resources.xml:
    <bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    		<property name="jndiName" value="java:/ConnectionFactory"/>
    	</bean>

JBossMQ (running outside JBossAS)

This applies to Grails application deployed outside JBossAS or in a separate JBossAS instance from the one running JBossMQ.

  1. Download JBossAS from http://labs.jboss.com/jbossas/
  2. Add jbossall-client.jar (from JBOSS_HOME/client) to the lib directory of your Grails application
  3. Add this to your conf/spring/resources.xml:
    <bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    		<property name="jndiName" value="ConnectionFactory" />
    		<property name="jndiEnvironment">
    			<props>
    				<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
    				<prop key="java.naming.provider.url">localhost:1099</prop>
    			</props>
    		</property>
    	</bean>

Version History

  • 0.1 - First Version
  • 0.2 - Adding sending functionality
  • 0.3 - Ensure that services aren't exposed until domain class dynamic methods are available; added durable and messageSelector options (thanks to Maxwell C. Xandeco)
</