Invert order of suppressed exceptions (for common exception rendering)
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions Details
Deploy Docs / Dispatch docs deployment (push) Waiting to run Details

See gh-35057
This commit is contained in:
Juergen Hoeller 2025-06-24 22:22:45 +02:00
parent 90c875144a
commit e828bbbb0a
2 changed files with 3 additions and 6 deletions

View File

@ -19,7 +19,6 @@ package org.springframework.core.retry;
import java.time.Duration; import java.time.Duration;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Deque; import java.util.Deque;
import java.util.Iterator;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
@ -203,9 +202,7 @@ public class RetryTemplate implements RetryOperations {
RetryException finalException = new RetryException( RetryException finalException = new RetryException(
"Retry policy for operation '%s' exhausted; aborting execution".formatted(retryableName), "Retry policy for operation '%s' exhausted; aborting execution".formatted(retryableName),
exceptions.removeLast()); exceptions.removeLast());
for (Iterator<Throwable> it = exceptions.descendingIterator(); it.hasNext();) { exceptions.forEach(finalException::addSuppressed);
finalException.addSuppressed(it.next());
}
this.retryListener.onRetryPolicyExhaustion(retryExecution, finalException); this.retryListener.onRetryPolicyExhaustion(retryExecution, finalException);
throw finalException; throw finalException;
} }

View File

@ -178,8 +178,8 @@ class RetryTemplateTests {
.withMessage("Retry policy for operation 'test' exhausted; aborting execution") .withMessage("Retry policy for operation 'test' exhausted; aborting execution")
.withCauseExactlyInstanceOf(IllegalStateException.class) .withCauseExactlyInstanceOf(IllegalStateException.class)
.satisfies(hasSuppressedExceptionsSatisfyingExactly( .satisfies(hasSuppressedExceptionsSatisfyingExactly(
suppressed1 -> assertThat(suppressed1).isExactlyInstanceOf(IOException.class), suppressed1 -> assertThat(suppressed1).isExactlyInstanceOf(FileNotFoundException.class),
suppressed2 -> assertThat(suppressed2).isExactlyInstanceOf(FileNotFoundException.class) suppressed2 -> assertThat(suppressed2).isExactlyInstanceOf(IOException.class)
)); ));
// 3 = 1 initial invocation + 2 retry attempts // 3 = 1 initial invocation + 2 retry attempts
assertThat(invocationCount).hasValue(3); assertThat(invocationCount).hasValue(3);