2015-06-08, Sven Ehrke (@syendar)
Introduction
In a recent project we had a grails application listening on a JMS MQ for incoming requests.
To do this we used the Grails JMS Plugin.
Problem
During certain times the listening has to be stopped so that no incoming messages would be processed anymore.
Unfortunately access to the queue is declared in a declarative manner:
class MqListenerService {
@Queue(name = '...')
def getIncomingQueue(message) {
...
String response = ...
return response
}
}
Now the question is how to tell it to stop/start listening.
Solution
With the so called container which is responsible for listening to the queue you can do it. The container is accessible via a Spring bean. It’s name is constructed from the classname containing the @Queue annotations (mqListener from MqListenerService in this case) and the methodname with the annotation (GetIncomingQueue from getIncomingQueue() in this case). Therefore the pattern is: <classname><methodname>_JmsListenerContainer. In our case this results to: _mqListenerGetIncomingQueueJmsListenerContainer
If you are not sure about the name you can always get a list of all Spring bean names like this:
GrailsApplication grailsApplication
@PostConstruct
protected void init() {
grailsApplication.mainContext.getBeanDefinitionNames().each { println "beanName: $it" }
}
With the name you should be able inject it into a controller and then call stop(), _start() and isRunning() on it:
DefaultMessageListenerContainer mqListenerGetIncomingQueueJmsListenerContainer
In our case we had to do it from an unmanaged class and so we had to get the bean from the Spring Applicationcontext and cast it to a DefaultMessageListenerContainer before we could use it:
class QueueHandler {
private final String CONTAINER_NAME = "mqListenerGetIncomingQueueJmsListenerContainer"
@Autowired
GrailsApplication grailsApplication;
private DefaultMessageListenerContainer myContainer;
@PostConstruct
protected void init() {
if (grailsApplication.getMainContext().containsBean(CONTAINER_NAME)) {
myContainer = (DefaultMessageListenerContainer) grailsApplication.getMainContext()
.getBean(CONTAINER_NAME);
}
}
public void stopListener() {
myContainer.stop();
}
public void startListener() {
myContainer.start();
}
public boolean isListening() {
myContainer.isRunning();
}
}
That’s it
I hope this post is useful if you have the same problem in one of your Grails based projects.
Based on Grails 2.4.4