Skip to content

Commit 4dc0976

Browse files
authored
GH-3463: Allow @DltHandler on super class (#3464)
Fixes: #3463 Currently, a `@DltHandler`-annotated method must be in the same class as the corresponding `@KafkaListener` annotation. Some logic might be the same for different `@KafkaListener` services. * Use `MethodIntrospector` in the `RetryableTopicAnnotationProcessor` to be able to process methods from super classes as well **Auto-cherry-pick to `3.2.x` & `3.1.x`**
1 parent 1318092 commit 4dc0976

File tree

2 files changed

+25
-30
lines changed

2 files changed

+25
-30
lines changed

spring-kafka/src/main/java/org/springframework/kafka/annotation/RetryableTopicAnnotationProcessor.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
3535
import org.springframework.context.expression.BeanFactoryResolver;
3636
import org.springframework.context.expression.StandardBeanExpressionResolver;
37+
import org.springframework.core.MethodIntrospector;
3738
import org.springframework.core.annotation.AnnotationUtils;
3839
import org.springframework.expression.spel.support.StandardEvaluationContext;
3940
import org.springframework.kafka.core.KafkaOperations;
@@ -64,6 +65,7 @@
6465
* @author Gary Russell
6566
* @author Adrian Chlebosz
6667
* @author Wang Zhiyang
68+
* @author Artem Bilan
6769
*
6870
* @since 2.7
6971
*
@@ -228,8 +230,10 @@ private Map<String, Set<Class<? extends Throwable>>> createDltRoutingSpecFromAnn
228230
}
229231

230232
private EndpointHandlerMethod getDltProcessor(Class<?> clazz, Object bean) {
231-
return Arrays.stream(ReflectionUtils.getDeclaredMethods(clazz))
232-
.filter(method -> AnnotationUtils.findAnnotation(method, DltHandler.class) != null)
233+
ReflectionUtils.MethodFilter selector =
234+
(method) -> AnnotationUtils.findAnnotation(method, DltHandler.class) != null;
235+
return MethodIntrospector.selectMethods(clazz, selector)
236+
.stream()
233237
.map(method -> RetryTopicConfigurer.createHandlerMethodWith(bean, method))
234238
.findFirst()
235239
.orElse(RetryTopicConfigurer.DEFAULT_DLT_HANDLER);

spring-kafka/src/test/java/org/springframework/kafka/retrytopic/RetryTopicClassLevelIntegrationTests.java

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
* Test class level non-blocking retries.
9494
*
9595
* @author Wang Zhiyang
96+
* @author Artem Bilan
9697
*
9798
* @since 3.2
9899
*/
@@ -227,7 +228,6 @@ void shouldRetryFifthTopicWithTwoListenersAndManualAssignment(@Autowired FifthTo
227228
assertThat(awaitLatch(latchContainer.countDownLatch51)).isTrue();
228229
assertThat(awaitLatch(latchContainer.countDownLatch52)).isTrue();
229230
assertThat(awaitLatch(latchContainer.countDownLatchDltThree)).isTrue();
230-
assertThat(awaitLatch(latchContainer.countDownLatchDltFour)).isTrue();
231231
assertThat(listener1.topics).containsExactly(TWO_LISTENERS_TOPIC, TWO_LISTENERS_TOPIC
232232
+ "-listener1-0", TWO_LISTENERS_TOPIC + "-listener1-1", TWO_LISTENERS_TOPIC + "-listener1-2",
233233
TWO_LISTENERS_TOPIC + "-listener1-dlt");
@@ -387,6 +387,21 @@ public void shouldNotGetHere() {
387387
}
388388
}
389389

390+
static class AbstractFifthTopicListener {
391+
392+
final List<String> topics = Collections.synchronizedList(new ArrayList<>());
393+
394+
@Autowired
395+
CountDownLatchContainer container;
396+
397+
@DltHandler
398+
public void annotatedDltMethod(ConsumerRecord<?, ?> record) {
399+
this.topics.add(record.topic());
400+
container.countDownLatchDltThree.countDown();
401+
}
402+
403+
}
404+
390405
@RetryableTopic(attempts = "4",
391406
backoff = @Backoff(250),
392407
numPartitions = "2",
@@ -397,12 +412,7 @@ public void shouldNotGetHere() {
397412
@KafkaListener(id = "fifthTopicId1", topicPartitions = {@TopicPartition(topic = TWO_LISTENERS_TOPIC,
398413
partitionOffsets = @PartitionOffset(partition = "0", initialOffset = "0"))},
399414
containerFactory = MAIN_TOPIC_CONTAINER_FACTORY)
400-
static class FifthTopicListener1 {
401-
402-
final List<String> topics = Collections.synchronizedList(new ArrayList<>());
403-
404-
@Autowired
405-
CountDownLatchContainer container;
415+
static class FifthTopicListener1 extends AbstractFifthTopicListener {
406416

407417
@KafkaHandler
408418
public void listenWithAnnotation(String message, @Header(KafkaHeaders.RECEIVED_TOPIC) String receivedTopic) {
@@ -411,12 +421,6 @@ public void listenWithAnnotation(String message, @Header(KafkaHeaders.RECEIVED_T
411421
throw new RuntimeException("Annotated woooops... " + receivedTopic);
412422
}
413423

414-
@DltHandler
415-
public void annotatedDltMethod(ConsumerRecord<?, ?> record) {
416-
this.topics.add(record.topic());
417-
container.countDownLatchDltThree.countDown();
418-
}
419-
420424
}
421425

422426
@RetryableTopic(attempts = "4",
@@ -429,12 +433,7 @@ public void annotatedDltMethod(ConsumerRecord<?, ?> record) {
429433
@KafkaListener(id = "fifthTopicId2", topicPartitions = {@TopicPartition(topic = TWO_LISTENERS_TOPIC,
430434
partitionOffsets = @PartitionOffset(partition = "1", initialOffset = "0"))},
431435
containerFactory = MAIN_TOPIC_CONTAINER_FACTORY)
432-
static class FifthTopicListener2 {
433-
434-
final List<String> topics = Collections.synchronizedList(new ArrayList<>());
435-
436-
@Autowired
437-
CountDownLatchContainer container;
436+
static class FifthTopicListener2 extends AbstractFifthTopicListener {
438437

439438
@KafkaHandler
440439
public void listenWithAnnotation2(String message, @Header(KafkaHeaders.RECEIVED_TOPIC) String receivedTopic) {
@@ -443,12 +442,6 @@ public void listenWithAnnotation2(String message, @Header(KafkaHeaders.RECEIVED_
443442
throw new RuntimeException("Annotated woooops... " + receivedTopic);
444443
}
445444

446-
@DltHandler
447-
public void annotatedDltMethod(ConsumerRecord<?, ?> record) {
448-
this.topics.add(record.topic());
449-
container.countDownLatchDltFour.countDown();
450-
}
451-
452445
}
453446

454447
@Component
@@ -575,9 +568,7 @@ static class CountDownLatchContainer {
575568

576569
CountDownLatch countDownLatchDltTwo = new CountDownLatch(1);
577570

578-
CountDownLatch countDownLatchDltThree = new CountDownLatch(1);
579-
580-
CountDownLatch countDownLatchDltFour = new CountDownLatch(1);
571+
CountDownLatch countDownLatchDltThree = new CountDownLatch(2);
581572

582573
CountDownLatch countDownLatchReuseOne = new CountDownLatch(2);
583574

0 commit comments

Comments
 (0)