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:

SomeController.groovy
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:

SomeController.groovy
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:

QueueHandler.java
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