(Quick Reference)
5 Receiving Messages
Version: 2.0.0.RC2
5 Receiving Messages
5.1 Service Listeners
Service Listeners
Service listeners are a convenient way to define one handler for JMS messages. The simplest service listener looks like…
class PersonService {
static exposes = ["jms"]
def onMessage(msg) {
// handle message
}
}
This will register the
onMessage
method as a listener for the JMS
queue named
«application name».person
, where «application name» is the
app.name
key from the
application.properties
file.
Configuration
The following configuration parameters can be set as static variables on the service class…
Property Name | Type | Default | Description |
---|
destination | String | «app name».«service name» | The named destination of the listener |
isTopic | boolean | false | is the destination a topic ( true ) or a queue ( false ) |
selector | String | null | See the “Message Selector” section of http://java.sun.com/j2ee/1.4/docs/api/javax/jms/Message.html |
adapter | String | "standard" | The adapter to use for this listener |
container | String | "standard" | The container to use for this listener |
class PersonService {
static exposes = ["jms"]
static destination = "somethingHappened"
static isTopic = true
static adapter = "custom" def onMessage(msg) {
// handle message
}
}
5.2 Service Method Listeners
Service Method Listeners
Another avenue is to expose specific methods as message listeners via annotations. This looks like…
import grails.plugin.jms.*class PersonService {
static exposes = ["jms"] @Queue
def addPerson(msg) {
} @Subscriber
def somethingHappened(msg) {
}
}
The above configuration binds the
personService.addPerson()
method to a queue named
«app name».person.addPerson
and binds the method
personService.somethingHappened()
as a listener to the topic named
somethingHappened
.
Note that you still need to expose the class via '
static exposes = ["jms"]
.
@Queue Configuration
The following configuration parameters can be set as annotation parameters…
Property Name | Type | Default | Description |
---|
name | String | «app name».«service name».«method name» | The destination name for the queue |
selector | String | null | The message selector to apply (See the “Message Selector” section of http://java.sun.com/j2ee/1.4/docs/api/javax/jms/Message.html) |
adapter | String | "standard" | The adapter to use for this listener |
container | String | "standard" | The container to use for this listener |
Example…
import grails.plugin.jms.*class PersonService {
static exposes = ["jms"] @Queue(
name = "myQueue",
selector = "name IS NOT NULL"
)
def addPerson(msg) {
}
}
@Subscriber Configuration
The following configuration parameters can be set as annotation parameters…
Property Name | Type | Default | Description |
---|
topic | String | «method name» | The name of the topic to subscribe to |
selector | String | null | The message selector to apply (See the “Message Selector” section of ) |
adapter | String | "standard" | The adapter to use for this listener |
container | String | "standard" | The container to use for this listener |
Example…
import grails.plugin.jms.*class PersonService {
static exposes = ["jms"] @Subscriber(topic = "aTopic")
def somethingHappened(msg) {
}
}
Defining the Queue names and Subscriber topics through configuration.
You can specify the names of the given
destinations ,
queues and
topics , described through the
Queue and Subscriber annotations by prefixing the
key with a Dollar sign (
$
). The key needs to be
available through the
Config.groovy
file in the
jms.destinations
space, if its not available an
error will be thrown.
Example…
PersonService.groovy
import grails.plugin.jms.*class PersonService {
static exposes = ["jms"] @Subscriber(topic = '$topic.key.in.config')
def somethingHappened(msg) {
} @Queue(name = '$queue.key.in.config')
def someWorkToDo(msg) {
}
}
Config.groovy
jms {
destinations {
//Name of the topic in the JMS server will be person.somethingHappened
topic.key.in.config = 'person.somethingHappened' //Name of the queue in the JMS server will be person.sendSomeWork
queue.key.in.config = 'person.sendSomeWork'
}
}
5.3 Listener Return Values
Spring's
MessageListenerAdapter adds some special handling of listener method return values.
From MessageListenerAdapter's JavaDoc: "If a target listener method returns a non-null object (typically of a message content type such as String or byte array), it will get wrapped in a JMS Message and sent to the response destination (either the JMS "reply-to" destination or a specified default destination)."
Be careful with Groovy's implicit return mechanism; ensure that you return null explicitly if you want nothing to be sent to the reply destination. If you accidentally return a value that cannot be sent to the reply destination, you may have odd side effects like messages never being removed from the queue (due to implicit rollbacks!).
5.4 Using Other Containers Or Adapters
Here is an example of using a container and adapter other than standard.
resources.groovy
import org.apache.activemq.ActiveMQConnectionFactory
import org.springframework.jms.connection.SingleConnectionFactorybeans = {
// used by the standard template by convention
jmsConnectionFactory(SingleConnectionFactory) {
targetConnectionFactory = { ActiveMQConnectionFactory cf ->
brokerURL = 'vm://localhost'
}
} otherJmsConnectionFactory(SingleConnectionFactory) {
targetConnectionFactory = { ActiveMQConnectionFactory cf ->
brokerURL = // … something else
}
}
}
Config.groovy
jms {
containers {
other {
meta {
parentBean = 'standardJmsListenerContainer'
}
concurrentConsumers = 5
connectionFactoryBean = "otherJmsConnectionFactory"
}
}
adapters {
other {
meta {
parentBean = 'standardJmsListenerAdapter'
}
messageConverter = null // do no message conversion
}
}
}
Sending messages
class ListeningService {
static exposes = ["jms"]
static adapter = "other"
static container = "other" def onMessage(msg) {
// handle message
}
}
import grails.plugin.jms.*class ListeningService {
static exposes = ["jms"] @Queue(adapter = "other", container = "other")
def receive(msg) {
// handle message
}
}