From 52e02deb538dc66e7e1c1c91e69a9af079fa829b Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 20 May 2019 17:19:00 +0200 Subject: [PATCH] Configurable connection recovery in SimpleMessageListenerContainer Closes gh-22987 --- .../SimpleMessageListenerContainer.java | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/spring-jms/src/main/java/org/springframework/jms/listener/SimpleMessageListenerContainer.java b/spring-jms/src/main/java/org/springframework/jms/listener/SimpleMessageListenerContainer.java index 0067fcded1..44066ff363 100644 --- a/spring-jms/src/main/java/org/springframework/jms/listener/SimpleMessageListenerContainer.java +++ b/spring-jms/src/main/java/org/springframework/jms/listener/SimpleMessageListenerContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -66,6 +66,8 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta private boolean connectLazily = false; + private boolean recoverOnException = true; + private int concurrentConsumers = 1; @Nullable @@ -94,6 +96,21 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta this.connectLazily = connectLazily; } + /** + * Specify whether to explicitly recover the shared JMS Connection and the + * associated Sessions and MessageConsumers whenever a JMSException is reported. + *

Default is "true": refreshing the shared connection and re-initializing the + * consumers whenever the connection propagates an exception to its listener. + * Set this flag to "false" in order to rely on automatic recovery within the + * provider, holding on to the existing connection and consumer handles. + * @since 5.1.8 + * @see #onException(JMSException) + * @see Connection#setExceptionListener + */ + public void setRecoverOnException(boolean recoverOnException) { + this.recoverOnException = recoverOnException; + } + /** * Specify concurrency limits via a "lower-upper" String, e.g. "5-10", or a simple * upper limit String, e.g. "10". @@ -227,8 +244,11 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta /** * JMS ExceptionListener implementation, invoked by the JMS provider in * case of connection failures. Re-initializes this listener container's - * shared connection and its sessions and consumers. + * shared connection and its sessions and consumers, if necessary. * @param ex the reported connection exception + * @see #setRecoverOnException + * @see #refreshSharedConnection() + * @see #initializeConsumers() */ @Override public void onException(JMSException ex) { @@ -236,21 +256,23 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta invokeExceptionListener(ex); // Now try to recover the shared Connection and all consumers... - if (logger.isDebugEnabled()) { - logger.debug("Trying to recover from JMS Connection exception: " + ex); - } - try { - synchronized (this.consumersMonitor) { - this.sessions = null; - this.consumers = null; + if (this.recoverOnException) { + if (logger.isDebugEnabled()) { + logger.debug("Trying to recover from JMS Connection exception: " + ex); + } + try { + synchronized (this.consumersMonitor) { + this.sessions = null; + this.consumers = null; + } + refreshSharedConnection(); + initializeConsumers(); + logger.debug("Successfully refreshed JMS Connection"); + } + catch (JMSException recoverEx) { + logger.debug("Failed to recover JMS Connection", recoverEx); + logger.error("Encountered non-recoverable JMSException", ex); } - refreshSharedConnection(); - initializeConsumers(); - logger.debug("Successfully refreshed JMS Connection"); - } - catch (JMSException recoverEx) { - logger.debug("Failed to recover JMS Connection", recoverEx); - logger.error("Encountered non-recoverable JMSException", ex); } }