web-dev-qa-db-ja.com

例外が発生した場合でもSpringJMSリスナーが確認

JMSを使用してSQSキューとメッセージを送受信していますが、client_acknowledgeを使用している場合でも、例外があるとメッセージを再配信できません。これを達成する方法は?簡単なテストを試しましたが、

@JmsListener(destination = "test-normalqueue")
public void receiveNormalQueue(String message)
{

    try {
        logger.info("message received in normal queue: " + message);
        throw new NullPointerException();

    } catch (Exception e) {

        logger.error(LoggingUtil.getStackTrace(e));;
    }

}

例外メッセージがキューに戻らない場合でも。

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(getSQSConnectionFactory());
    factory.setConcurrency("1-2");
    factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
    return factory;
}
8
Bhargav

DMLCでトランザクションを使用する必要があります。

_Session.AUTO_ACKNOWLEDGE_およびsetSessionTransacted(true)を使用します。

リスナーが正常に終了すると、メッセージは削除されます。リスナーthrows例外の場合、メッセージはキューにロールバックされます。

トランザクションでクライアントモードを使用することもできますが、成功したメッセージを自分で確認する必要があります。

SimpleMessageListenerContainerでトランザクションを使用する必要はありませんが、メッセージを再キューに入れるために例外をスローする必要があります。

5
Gary Russell

メッセージは、リスナーが停止してブローカーから切断された場合にのみキューに戻ります。説明している動作は、リスナーにメッセージをディスパッチし、例外と再試行を管理するDefaultMessageListenerContainerのクライアント側にあり、ブローカーはそれらの処理を認識しません。そして彼は、これらのメッセージがクライアントにディスパッチされ、確認応答を待っていることだけを知っています。 MessageConsumerの実装でリセットや再起動などのメソッドがあるかどうかは、SQSのメソッドと機能に依存します。 jmsセッションのrecover()メソッドを試すことができますが、これはクライアント側でのみ配信を再開すると思います。 https://docs.Oracle.com/javaee/7/api/javax/jms/Session.html#recover--

これはお勧めできませんが、接続またはDefaultMessageListenerContainerを再起動すると、確認応答されなかったメッセージがブローカーに返され、配信が再開されます。

0
Hassen Bennour