7676import org .springframework .kafka .listener .KafkaListenerErrorHandler ;
7777import org .springframework .kafka .support .KafkaNull ;
7878import org .springframework .kafka .support .TopicPartitionOffset ;
79+ import org .springframework .lang .Nullable ;
7980import org .springframework .messaging .Message ;
8081import org .springframework .messaging .converter .GenericMessageConverter ;
8182import org .springframework .messaging .converter .MessageConverter ;
@@ -564,7 +565,7 @@ private List<TopicPartitionOffset> resolveTopicPartitionsList(TopicPartition top
564565 () -> "At least one 'partition' or 'partitionOffset' required in @TopicPartition for topic '" + topic + "'" );
565566 List <TopicPartitionOffset > result = new ArrayList <>();
566567 for (String partition : partitions ) {
567- resolvePartitionAsInteger ((String ) topic , resolveExpression (partition ), result );
568+ resolvePartitionAsInteger ((String ) topic , resolveExpression (partition ), result , null , false , false );
568569 }
569570 if (partitionOffsets .length == 1 && partitionOffsets [0 ].partition ().equals ("*" )) {
570571 result .forEach (tpo -> {
@@ -576,19 +577,8 @@ private List<TopicPartitionOffset> resolveTopicPartitionsList(TopicPartition top
576577 for (PartitionOffset partitionOffset : partitionOffsets ) {
577578 Assert .isTrue (!partitionOffset .partition ().equals ("*" ), () ->
578579 "Partition wildcard '*' is only allowed in a single @PartitionOffset in " + result );
579- TopicPartitionOffset topicPartitionOffset =
580- new TopicPartitionOffset ((String ) topic ,
581- resolvePartition (topic , partitionOffset ),
582- resolveInitialOffset (topic , partitionOffset ),
583- isRelative (topic , partitionOffset ));
584- if (!result .contains (topicPartitionOffset )) {
585- result .add (topicPartitionOffset );
586- }
587- else {
588- throw new IllegalArgumentException (
589- String .format ("@TopicPartition can't have the same partition configuration twice: [%s]" ,
590- topicPartitionOffset ));
591- }
580+ resolvePartitionAsInteger ((String ) topic , resolveExpression (partitionOffset .partition ()), result ,
581+ resolveInitialOffset (topic , partitionOffset ), isRelative (topic , partitionOffset ), true );
592582 }
593583 }
594584 Assert .isTrue (result .size () > 0 , () -> "At least one partition required for " + topic );
@@ -673,18 +663,27 @@ else if (resolvedValue instanceof Iterable) {
673663
674664 @ SuppressWarnings ("unchecked" )
675665 private void resolvePartitionAsInteger (String topic , Object resolvedValue ,
676- List <TopicPartitionOffset > result ) {
666+ List <TopicPartitionOffset > result , @ Nullable Long offset , boolean isRelative , boolean checkDups ) {
667+
677668 if (resolvedValue instanceof String []) {
678669 for (Object object : (String []) resolvedValue ) {
679- resolvePartitionAsInteger (topic , object , result );
670+ resolvePartitionAsInteger (topic , object , result , offset , isRelative , checkDups );
680671 }
681672 }
682673 else if (resolvedValue instanceof String ) {
683674 Assert .state (StringUtils .hasText ((String ) resolvedValue ),
684675 () -> "partition in @TopicPartition for topic '" + topic + "' cannot be empty" );
685- result .addAll (parsePartitions ((String ) resolvedValue )
686- .map (part -> new TopicPartitionOffset (topic , part ))
687- .collect (Collectors .toList ()));
676+ List <TopicPartitionOffset > collected = parsePartitions ((String ) resolvedValue )
677+ .map (part -> new TopicPartitionOffset (topic , part , offset , isRelative ))
678+ .collect (Collectors .toList ());
679+ if (checkDups ) {
680+ collected .forEach (tpo -> {
681+ Assert .state (!result .contains (tpo ), () ->
682+ String .format ("@TopicPartition can't have the same partition configuration twice: [%s]" ,
683+ tpo ));
684+ });
685+ }
686+ result .addAll (collected );
688687 }
689688 else if (resolvedValue instanceof Integer []) {
690689 for (Integer partition : (Integer []) resolvedValue ) {
@@ -696,7 +695,7 @@ else if (resolvedValue instanceof Integer) {
696695 }
697696 else if (resolvedValue instanceof Iterable ) {
698697 for (Object object : (Iterable <Object >) resolvedValue ) {
699- resolvePartitionAsInteger (topic , object , result );
698+ resolvePartitionAsInteger (topic , object , result , offset , isRelative , checkDups );
700699 }
701700 }
702701 else {
0 commit comments