GH-9297: Improve ImapIdleChannelAdapter.callIdle() for cause
Fixes: #9297 For a normal `jakarta.mail.StoreClosedException: * BYE Jakarta Mail Exception: java.net.SocketException: Connection reset` the `ImapIdleChannelAdapter.callIdle()` results in a resubmission (and reconnection) with logging 'Failed to execute IDLE task. Will attempt to resubmit in 10000 milliseconds.'` However, when `selectorExpression` is in used and that one is based on mail `Message` object, we may fail with `FolderClosedException` which is wrapped to the `SpelEvaluationException` and some other stack traces. So, `jakarta.mail.MessagingException` might be deep in the cause chain. * Fix `ImapIdleChannelAdapter` via introducing `getJakartaMailMessagingExceptionFromCause()` utility method which searches for the `jakarta.mail.MessagingException` in cause chain. * Rework `ImapIdleChannelAdapter.callIdle()` logic to rely on this new method **Auto-cherry-pick to `6.3.x` & `6.2.x`**
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -36,6 +36,7 @@ import org.springframework.integration.mail.event.MailIntegrationEvent;
|
||||
import org.springframework.integration.transaction.IntegrationResourceHolder;
|
||||
import org.springframework.integration.transaction.IntegrationResourceHolderSynchronization;
|
||||
import org.springframework.integration.transaction.TransactionSynchronizationFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
@@ -200,22 +201,24 @@ public class ImapIdleChannelAdapter extends MessageProducerSupport implements Be
|
||||
}
|
||||
catch (Exception ex) {
|
||||
publishException(ex);
|
||||
if (this.shouldReconnectAutomatically
|
||||
&& ex.getCause() instanceof jakarta.mail.MessagingException messagingException) {
|
||||
if (this.shouldReconnectAutomatically) {
|
||||
jakarta.mail.MessagingException messagingException =
|
||||
getJakartaMailMessagingExceptionFromCause(ex.getCause());
|
||||
|
||||
//run again after a delay
|
||||
logger.info(messagingException,
|
||||
() -> "Failed to execute IDLE task. Will attempt to resubmit in "
|
||||
+ this.reconnectDelay + " milliseconds.");
|
||||
delayNextIdleCall();
|
||||
}
|
||||
else {
|
||||
logger.warn(ex,
|
||||
"Failed to execute IDLE task. " +
|
||||
"Won't resubmit since not a 'shouldReconnectAutomatically' " +
|
||||
"or not a 'jakarta.mail.MessagingException'");
|
||||
break;
|
||||
if (messagingException != null) {
|
||||
//run again after a delay
|
||||
logger.info(messagingException,
|
||||
() -> "Failed to execute IDLE task. Will attempt to resubmit in "
|
||||
+ this.reconnectDelay + " milliseconds.");
|
||||
delayNextIdleCall();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
logger.warn(ex,
|
||||
"Failed to execute IDLE task. " +
|
||||
"Won't resubmit since not a 'shouldReconnectAutomatically' " +
|
||||
"or not a 'jakarta.mail.MessagingException'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,6 +259,21 @@ public class ImapIdleChannelAdapter extends MessageProducerSupport implements Be
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static jakarta.mail.MessagingException getJakartaMailMessagingExceptionFromCause(Throwable cause) {
|
||||
if (cause == null) {
|
||||
return null;
|
||||
}
|
||||
if (cause instanceof jakarta.mail.MessagingException messagingException) {
|
||||
return messagingException;
|
||||
}
|
||||
Throwable nextCause = cause.getCause();
|
||||
if (cause == nextCause) {
|
||||
return null;
|
||||
}
|
||||
return getJakartaMailMessagingExceptionFromCause(nextCause);
|
||||
}
|
||||
|
||||
private class MessageSender implements Consumer<Object> {
|
||||
|
||||
MessageSender() {
|
||||
|
||||
Reference in New Issue
Block a user