Контейнер слушателя Spring JMS останавливает только половину слушателей

У меня возникла проблема с контейнером прослушивателя JMS. Если я отключу контейнер слушателя, половина сообщений доставляется и обрабатывается слушателем. Вот моя конфигурация Spring:

<bean id="ConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="JmsXA" />
</bean>

<bean id="testQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="queue/test" />
</bean>

<bean id="listener" class="eu.cuptech.jms.listener.ExampleListener" />

<bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="ConnectionFactory" />
    <property name="destination" ref="testQueue" />
    <property name="messageListener" ref="listener" />
    <property name="concurrency" value="1" />
</bean>

ExampleListener здесь:

package eu.cuptech.jms.listener;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

public class ExampleListener implements MessageListener {

    public void onMessage(Message message) {
        try {
            String msg = ((TextMessage) message).getText();
            System.out.println("MESSAGE TEXT: " + msg);
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }

}

Клиент - Spring MVC Controller со следующими методами:

Метод send10Messages (обычный клиент JMS):

@Resource(name="ConnectionFactory")
private ConnectionFactory connectionFactory;

@Resource(name="testQueue")
private Queue testQueue;

@RequestMapping(value="send10", method = RequestMethod.GET)
public String send10Messages(ModelMap model, HttpSession session) throws Exception {
    sendTextMessages(10, "Test message: ");
    return "redirect:/info";
}

private void sendTextMessages(int count, final String prefix) throws Exception {
    Connection connection = null;
    Session session = null;
    MessageProducer messageProducer = null;
    try {
        connection = connectionFactory.createConnection();

        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        messageProducer = session.createProducer(testQueue);
        connection.start();
        TextMessage message = session.createTextMessage();

        int i = 0;
        while (i < count) {
            message.setText(prefix + ++i);
            messageProducer.send(message);
            Thread.sleep(250);
            System.out.println("Message " + prefix + i + " sent.");
        }

    } finally {
        try {
            if (messageProducer != null)
                messageProducer.close();
            if (connection != null)
                connection.close();
            if (session != null)
                session.close();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

disableListener метод:

@Resource(name="listenerContainer")
private DefaultMessageListenerContainer listenerContainer;

@RequestMapping(value="disableListener", method = RequestMethod.GET)
public String disableListener(ModelMap model, HttpSession session) {
    listenerContainer.stop(new Runnable() {
        public void run() {
            System.out.println("JMS Listener stopped.");
        }
    });
    return "redirect:/info";
}

enableListener метод

@Resource(name="listenerContainer")
private DefaultMessageListenerContainer listenerContainer;

@RequestMapping(value="enableListener", method = RequestMethod.GET)
public String enableListener(ModelMap model, HttpSession session) {
    listenerContainer.start();
    return "redirect:/info";
}

Когда я запускаю сервер и отправляю сообщения, я получил этот журнал (все в порядке):

INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 1
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 1 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 2
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 2 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 3
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 3 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 4
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 4 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 5
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 5 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 6
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 6 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 7
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 7 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 8
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 8 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 9
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 9 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 10
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 10 sent.

Когда я отключил контейнер слушателя и снова отправил сообщения, я получил следующее:

INFO [stdout] (listenerContainer-1) JMS Listener stopped.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 1
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 1 sent.
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 2 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 3
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 3 sent.
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 4 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 5
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 5 sent.
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 6 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 7
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 7 sent.
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 8 sent.
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 9
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 9 sent.
INFO [stdout] (http-localhost/127.0.0.1:8080-1) Message Test message: 10 sent.

Когда я снова включаю контейнер слушателя, я получаю следующее:

INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 2
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 4
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 6
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 8
INFO [stdout] (listenerContainer-1) MESSAGE TEXT: Test message: 10

Проблема в том, что каждое нечетное сообщение обрабатывается слушателем, даже если слушатель отключен. Я заявляю, что все сообщения будут доставляться и обрабатываться слушателем, когда я включаю контейнер слушателя, и никакое сообщение не будет обрабатываться, когда я его отключу.

Я использую Spring 3.2.4.RELEASE (я тоже пробовал 3.2.3.RELEASE), HornetQ 2.3.0.Final в качестве удаленного сервера JMS и JBoss 7.3.1.Final в качестве сервера приложений.


person Boris Šuška    schedule 23.08.2013    source источник


Ответы (1)


Я предполагаю, что вы загружаете контейнер как в веб-контекст (контекст DispatcherServlet), так и в корневой контекст (контекст ContextLoaderListener). Это означает, что у вас есть 2 контейнера, и вы останавливаете только один в контексте сервлета.

Включите DEBUG ведение журнала для org.springframework и изучите журналы инициализации bean-компонентов.

Вероятно, это должно быть только в корневом контексте.

person Gary Russell    schedule 23.08.2013
comment
Вы совершенно правы. У меня был тот же файл конфигурации, который использовали ContextLoaderListener и DispatcherServlet. Я начал с примера Mkyong, в котором он настроен . Спасибо. - person Boris Šuška; 23.08.2013
comment
Это, вероятно, также означает, что в фабрике соединений, которую вы получаете от JNDI, происходит какое-то кеширование предварительной выборки / потребителя - это объясняет, почему 5 сообщений застревают в ожидании повторного запуска этого конкретного контейнера. - person Gary Russell; 24.08.2013