Stopping Spring JMS listener results in strange behavior on ActiveMQ Classic

34 Views Asked by At

I have run into some strange behavior when starting and stopping JMS listeners. I have defined two listeners like so:

@JmsListener(id="myid", destination = "myDestination")
public void SampleJmsListenerMethod(String text) {
    System.out.println("1: "+text);
}

@JmsListener(id="myid2", destination = "myDestination")
public void SampleJmsListenerMethod2(String text) {
    System.out.println("2: "+text);
}

Using a REST controller I can start and stop one of them:

@RequestMapping(value="/halt", method= RequestMethod.GET)
public @ResponseBody
String haltJmsListener() {
    JmsListenerEndpointRegistry customRegistry =
            context.getBean(JmsListenerEndpointRegistry.class);
    Objects.requireNonNull(customRegistry.getListenerContainer("myid")).stop();
    return "Jms Listener Stopped";
}

@RequestMapping(value="/restart", method=RequestMethod.GET)
public @ResponseBody
String reStartJmsListener() {
    JmsListenerEndpointRegistry customRegistry =
            context.getBean(JmsListenerEndpointRegistry.class);
    Objects.requireNonNull(customRegistry.getListenerContainer("myid")).start();
    return "Jms Listener restarted";
}

When the application is started, I see two connections and two active consumers. The output on the console is:

Sending message to 'myDestination' destination with text hello
1: hello
Sending message to 'myDestination' destination with text hello
2: hello
Sending message to 'myDestination' destination with text hello
1: hello
Sending message to 'myDestination' destination with text hello
2: hello

If I stop one listener, I still see two connections and two consumers, but the output suddenly is:

Sending message to 'myDestination' destination with text hello
Sending message to 'myDestination' destination with text hello
2: hello
Sending message to 'myDestination' destination with text hello
Sending message to 'myDestination' destination with text hello
2: hello

So I only receive every second message. The other messages stay on the queue. If I then restart the listener, I get

1: hello
1: hello
Sending message to 'myDestination' destination with text hello
1: hello
Sending message to 'myDestination' destination with text hello
2: hello
Sending message to 'myDestination' destination with text hello
1: hello

So first the two messages, which were sent but not consumed. And then I'm back to normal and the messages are consumed round robin by on of the two listeners.

I've tested this with ActiveMQ Classic 5.15 (Spring 2.3.12) and 5.16 (Spring 2.7.8) and both exhibit this behavior.

If I do this in Spring 3.2.1 with 5.18 I do not see this behavior. If I stop the listener, all messages will come in on the remaining listener and the connection is removed.

Does anyone know if it is supposed to work like that or not?

1

There are 1 best solutions below

0
Pieter On

It seems older versions stop the listener, but do not release the connection. See also the comment to this answer: https://stackoverflow.com/a/57993175/900119

This explains the behavior I've noticed. It seems that newer versions also release the connection, thus allowing ActiveMQ to redirect messages to other consumers.

For now I've solved this by not using the messagelistenercontainer, but only the connectionfactory and creating the connection, session and messageconsumer manually. I can close those again resulting in the desired behavior.

PS. there also seems to be a ticket with Spring to change this behavior: https://github.com/spring-projects/spring-framework/issues/30612