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;
}
DMLCでトランザクションを使用する必要があります。
_Session.AUTO_ACKNOWLEDGE
_およびsetSessionTransacted(true)
を使用します。
リスナーが正常に終了すると、メッセージは削除されます。リスナーthrows例外の場合、メッセージはキューにロールバックされます。
トランザクションでクライアントモードを使用することもできますが、成功したメッセージを自分で確認する必要があります。
SimpleMessageListenerContainer
でトランザクションを使用する必要はありませんが、メッセージを再キューに入れるために例外をスローする必要があります。
メッセージは、リスナーが停止してブローカーから切断された場合にのみキューに戻ります。説明している動作は、リスナーにメッセージをディスパッチし、例外と再試行を管理するDefaultMessageListenerContainerのクライアント側にあり、ブローカーはそれらの処理を認識しません。そして彼は、これらのメッセージがクライアントにディスパッチされ、確認応答を待っていることだけを知っています。 MessageConsumerの実装でリセットや再起動などのメソッドがあるかどうかは、SQSのメソッドと機能に依存します。 jmsセッションのrecover()メソッドを試すことができますが、これはクライアント側でのみ配信を再開すると思います。 https://docs.Oracle.com/javaee/7/api/javax/jms/Session.html#recover--
これはお勧めできませんが、接続またはDefaultMessageListenerContainerを再起動すると、確認応答されなかったメッセージがブローカーに返され、配信が再開されます。