diff --git a/spring-jms/src/main/java/org/springframework/jms/listener/DefaultMessageListenerContainer.java b/spring-jms/src/main/java/org/springframework/jms/listener/DefaultMessageListenerContainer.java index 7eb1d28610..9bd050a3fe 100644 --- a/spring-jms/src/main/java/org/springframework/jms/listener/DefaultMessageListenerContainer.java +++ b/spring-jms/src/main/java/org/springframework/jms/listener/DefaultMessageListenerContainer.java @@ -1040,6 +1040,11 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe } catch (Throwable ex) { clearResources(); + if (!this.lastMessageSucceeded) { + // We failed more than once in a row or on startup - sleep before + // first recovery attempt. + sleepBeforeRecoveryAttempt(); + } this.lastMessageSucceeded = false; boolean alreadyRecovered = false; synchronized (recoveryMonitor) { @@ -1191,6 +1196,17 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe this.session = null; } + /** + * Apply the back off time once. In a regular scenario, the back off is only applied if we + * failed to recover with the broker. This additional sleep period avoids a burst retry + * scenario when the broker is actually up but something else if failing (i.e. listener + * specific). + */ + private void sleepBeforeRecoveryAttempt() { + BackOffExecution execution = DefaultMessageListenerContainer.this.backOff.start(); + applyBackOffTime(execution); + } + @Override public boolean isLongLived() { return (maxMessagesPerTask < 0);