1616
1717package org .springframework .integration .jdbc .channel ;
1818
19+ import java .time .Duration ;
1920import java .util .Optional ;
2021import java .util .concurrent .Executor ;
2122
2223import org .jspecify .annotations .Nullable ;
2324
2425import org .springframework .core .log .LogAccessor ;
26+ import org .springframework .core .retry .RetryException ;
27+ import org .springframework .core .retry .RetryPolicy ;
28+ import org .springframework .core .retry .RetryTemplate ;
29+ import org .springframework .core .retry .Retryable ;
2530import org .springframework .core .task .SimpleAsyncTaskExecutor ;
2631import org .springframework .integration .channel .AbstractSubscribableChannel ;
2732import org .springframework .integration .dispatcher .MessageDispatcher ;
2833import org .springframework .integration .dispatcher .UnicastingDispatcher ;
2934import org .springframework .integration .jdbc .store .JdbcChannelMessageStore ;
3035import org .springframework .messaging .Message ;
3136import org .springframework .messaging .MessageHandler ;
32- import org .springframework .retry .support .RetryTemplate ;
3337import org .springframework .transaction .PlatformTransactionManager ;
3438import org .springframework .transaction .support .TransactionTemplate ;
3539import org .springframework .util .Assert ;
@@ -69,7 +73,8 @@ public class PostgresSubscribableChannel extends AbstractSubscribableChannel
6973
7074 private @ Nullable TransactionTemplate transactionTemplate ;
7175
72- private RetryTemplate retryTemplate = RetryTemplate .builder ().maxAttempts (1 ).build ();
76+ private RetryTemplate retryTemplate =
77+ new RetryTemplate (RetryPolicy .builder ().maxAttempts (1 ).delay (Duration .ZERO ).build ());
7378
7479 private ErrorHandler errorHandler = ReflectionUtils ::rethrowRuntimeException ;
7580
@@ -117,7 +122,7 @@ public void setTransactionManager(PlatformTransactionManager transactionManager)
117122 }
118123
119124 /**
120- * Set the retry template to use for retries in case of exception in downstream processing
125+ * Set the retry template to use it for retries in case of exception in downstream processing
121126 * @param retryTemplate The retry template to use
122127 * @since 6.0.5
123128 * @see RetryTemplate
@@ -207,7 +212,7 @@ private Optional<?> doPollAndDispatchMessage() {
207212 if (this .hasHandlers ) {
208213 TransactionTemplate transactionTemplateToUse = this .transactionTemplate ;
209214 if (transactionTemplateToUse != null ) {
210- return this . retryTemplate . execute ( context ->
215+ return executeWithRetry (() ->
211216 transactionTemplateToUse .execute (status ->
212217 pollMessage ()
213218 .filter (message -> {
@@ -221,12 +226,26 @@ private Optional<?> doPollAndDispatchMessage() {
221226 }
222227 else {
223228 return pollMessage ()
224- .map (message -> this . retryTemplate . execute ( context -> dispatch (message )));
229+ .map (message -> executeWithRetry (() -> dispatch (message )));
225230 }
226231 }
227232 return Optional .empty ();
228233 }
229234
235+ @ SuppressWarnings ("NullAway" ) // Never null, according to the logic in the 'doPollAndDispatchMessage()'.
236+ private <T > T executeWithRetry (Retryable <T > retryable ) {
237+ try {
238+ return this .retryTemplate .execute (retryable );
239+ }
240+ catch (RetryException ex ) {
241+ Throwable cause = ex .getCause ();
242+ if (cause instanceof RuntimeException runtimeException ) {
243+ throw runtimeException ;
244+ }
245+ throw new IllegalStateException (cause );
246+ }
247+ }
248+
230249 private Optional <Message <?>> pollMessage () {
231250 return Optional .ofNullable (this .jdbcChannelMessageStore .pollMessageFromGroup (this .groupId ));
232251 }
0 commit comments