3636import java .util .concurrent .atomic .AtomicBoolean ;
3737import java .util .concurrent .atomic .AtomicInteger ;
3838import java .util .concurrent .atomic .AtomicReference ;
39+ import java .util .function .Supplier ;
3940import java .util .stream .IntStream ;
4041
4142import com .fasterxml .jackson .databind .ObjectMapper ;
172173 * @author Henryk Konsek
173174 * @author Gary Russell
174175 * @author Chris Bono
175- * @Author Oliver Führer
176+ * @author Oliver Führer
177+ * @author Didier Loiseau
176178 */
177179@ EmbeddedKafka (count = 1 , controlledShutdown = true , topics = "error.pollableDlq.group-pcWithDlq" , brokerProperties = {"transaction.state.log.replication.factor=1" ,
178180 "transaction.state.log.min.isr=1" })
@@ -1052,11 +1054,41 @@ void dlqAndRetry() throws Exception {
10521054 testDlqGuts (true , null , null , false , false );
10531055 }
10541056
1057+ @ Test
1058+ void dlqAndRetryWithNonRetryableException () throws Exception {
1059+ testDlqGuts (true , null , null , false , false , true , true );
1060+ }
1061+
1062+ @ Test
1063+ void dlqAndRetryDefaultFalse () throws Exception {
1064+ testDlqGuts (true , null , null , false , false , false , false );
1065+ }
1066+
1067+ @ Test
1068+ void dlqAndRetryDefaultFalseWithRetryableException () throws Exception {
1069+ testDlqGuts (true , null , null , false , false , false , true );
1070+ }
1071+
10551072 @ Test
10561073 void dlqAndRetryTransactional () throws Exception {
10571074 testDlqGuts (true , null , null , true , false );
10581075 }
10591076
1077+ @ Test
1078+ void dlqAndRetryWithNonRetryableExceptionTransactional () throws Exception {
1079+ testDlqGuts (true , null , null , true , false , true , true );
1080+ }
1081+
1082+ @ Test
1083+ void dlqAndRetryDefaultFalseTransactional () throws Exception {
1084+ testDlqGuts (true , null , null , true , false , false , false );
1085+ }
1086+
1087+ @ Test
1088+ void dlqAndRetryDefaultFalseWithRetryableExceptionTransactional () throws Exception {
1089+ testDlqGuts (true , null , null , true , false , false , true );
1090+ }
1091+
10601092 @ Test
10611093 void dlq () throws Exception {
10621094 testDlqGuts (false , null , 3 , false , false );
@@ -1084,6 +1116,14 @@ void dlqEmbedded() throws Exception {
10841116
10851117 private void testDlqGuts (boolean withRetry , HeaderMode headerMode , Integer dlqPartitions ,
10861118 boolean transactional , boolean useDlqDestResolver ) throws Exception {
1119+ testDlqGuts (withRetry , headerMode , dlqPartitions , transactional ,
1120+ useDlqDestResolver , true , false );
1121+ }
1122+
1123+ private void testDlqGuts (boolean withRetry , HeaderMode headerMode ,
1124+ Integer dlqPartitions , boolean transactional , boolean useDlqDestResolver ,
1125+ boolean defaultRetryable , boolean useConfiguredRetryableException )
1126+ throws Exception {
10871127
10881128 int expectedDlqPartition = dlqPartitions == null ? 0 : dlqPartitions - 1 ;
10891129 KafkaBinderConfigurationProperties binderConfig = createConfigurationProperties ();
@@ -1128,12 +1168,18 @@ else if (dlqPartitions == null) {
11281168 consumerProperties .getExtension ().setDlqPartitions (dlqPartitions );
11291169 consumerProperties .setConcurrency (2 );
11301170 consumerProperties .populateBindingName ("foobar" );
1171+ consumerProperties .setDefaultRetryable (defaultRetryable );
1172+ consumerProperties .getRetryableExceptions ().put (NumberFormatException .class ,
1173+ !defaultRetryable );
11311174
11321175 DirectChannel moduleInputChannel = createBindableChannel ("input" ,
11331176 createConsumerBindingProperties (consumerProperties ));
11341177
11351178 var dlqChannel = new QueueChannel ();
1136- var handler = new FailingInvocationCountingMessageHandler ();
1179+ var handler = new FailingInvocationCountingMessageHandler (
1180+ () -> useConfiguredRetryableException
1181+ ? new NumberFormatException ("fail" )
1182+ : new RuntimeException ("fail" ));
11371183 moduleInputChannel .subscribe (handler );
11381184
11391185 long uniqueBindingId = System .currentTimeMillis ();
@@ -1253,8 +1299,10 @@ else if (dlqPartitions == null) {
12531299 .get (KafkaHeaders .RECEIVED_PARTITION )).isEqualTo (expectedDlqPartition );
12541300 }
12551301 else if (!HeaderMode .none .equals (headerMode )) {
1302+ boolean shouldHaveRetried = defaultRetryable != useConfiguredRetryableException ;
12561303 assertThat (handler .getInvocationCount ())
1257- .isEqualTo (consumerProperties .getMaxAttempts ());
1304+ .isEqualTo (
1305+ shouldHaveRetried ? consumerProperties .getMaxAttempts () : 1 );
12581306
12591307 assertThat (receivedMessage .getHeaders ()
12601308 .get (KafkaMessageChannelBinder .X_ORIGINAL_TOPIC ))
@@ -4090,14 +4138,27 @@ private static void assertionsOnKafkaTemplate(TestObservationRegistry observatio
40904138 private final class FailingInvocationCountingMessageHandler
40914139 implements MessageHandler {
40924140
4141+ private final Supplier <? extends RuntimeException > exceptionProvider ;
4142+
40934143 private volatile int invocationCount ;
40944144
40954145 private final LinkedHashMap <Long , Message <?>> receivedMessages = new LinkedHashMap <>();
40964146
40974147 private final CountDownLatch latch ;
40984148
4099- private FailingInvocationCountingMessageHandler (int latchSize ) {
4149+ private FailingInvocationCountingMessageHandler (int latchSize ,
4150+ Supplier <? extends RuntimeException > exceptionProvider ) {
41004151 latch = new CountDownLatch (latchSize );
4152+ this .exceptionProvider = exceptionProvider ;
4153+ }
4154+
4155+ private FailingInvocationCountingMessageHandler (
4156+ Supplier <? extends RuntimeException > exceptionProvider ) {
4157+ this (1 , exceptionProvider );
4158+ }
4159+
4160+ private FailingInvocationCountingMessageHandler (int latchSize ) {
4161+ this (latchSize , () -> new RuntimeException ("fail" ));
41014162 }
41024163
41034164 private FailingInvocationCountingMessageHandler () {
@@ -4115,7 +4176,7 @@ public void handleMessage(Message<?> message) throws MessagingException {
41154176 receivedMessages .put (offset , message );
41164177 latch .countDown ();
41174178 }
4118- throw new RuntimeException ( "fail" );
4179+ throw exceptionProvider . get ( );
41194180 }
41204181
41214182 public LinkedHashMap <Long , Message <?>> getReceivedMessages () {
0 commit comments