|
63 | 63 | import org.apache.kafka.common.errors.TopicExistsException;
|
64 | 64 | import org.apache.kafka.common.serialization.ByteArrayDeserializer;
|
65 | 65 | import org.apache.kafka.common.serialization.ByteArraySerializer;
|
| 66 | +import org.awaitility.Awaitility; |
66 | 67 | import org.jspecify.annotations.NonNull;
|
67 | 68 | import org.jspecify.annotations.Nullable;
|
68 | 69 | import org.junit.jupiter.api.Test;
|
|
141 | 142 | import org.springframework.messaging.converter.AbstractMessageConverter;
|
142 | 143 | import org.springframework.messaging.converter.SmartMessageConverter;
|
143 | 144 | import org.springframework.messaging.handler.annotation.Header;
|
| 145 | +import org.springframework.messaging.handler.annotation.Headers; |
144 | 146 | import org.springframework.messaging.handler.annotation.Payload;
|
145 | 147 | import org.springframework.messaging.handler.annotation.SendTo;
|
146 | 148 | import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException;
|
|
181 | 183 | * @author Soby Chacko
|
182 | 184 | * @author Wang Zhiyang
|
183 | 185 | * @author Borahm Lee
|
| 186 | + * @author Sean Sullivan |
184 | 187 | */
|
185 | 188 | @SpringJUnitConfig
|
186 | 189 | @DirtiesContext
|
|
196 | 199 | "annotated29", "annotated30", "annotated30reply", "annotated31", "annotated32", "annotated33",
|
197 | 200 | "annotated34", "annotated35", "annotated36", "annotated37", "foo", "manualStart", "seekOnIdle",
|
198 | 201 | "annotated38", "annotated38reply", "annotated39", "annotated40", "annotated41", "annotated42",
|
199 |
| - "annotated43", "annotated43reply", "seekToComputeFn"}) |
| 202 | + "annotated43", "annotated43reply", "seekToComputeFn", "headerMapTopic"}) |
200 | 203 | @TestPropertySource(properties = "spel.props=fetch.min.bytes=420000,max.poll.records=10")
|
201 | 204 | public class EnableKafkaIntegrationTests {
|
202 | 205 |
|
@@ -242,6 +245,9 @@ public class EnableKafkaIntegrationTests {
|
242 | 245 | @Autowired
|
243 | 246 | public MultiJsonListenerBean multiJsonListener;
|
244 | 247 |
|
| 248 | + @Autowired |
| 249 | + public HeaderMapListenerBean headerMapListener; |
| 250 | + |
245 | 251 | @Autowired
|
246 | 252 | public MultiListenerNoDefault multiNoDefault;
|
247 | 253 |
|
@@ -584,6 +590,50 @@ public void testMultiJson() throws Exception {
|
584 | 590 | assertThat(this.multiJsonListener.validated.valCount).isEqualTo(1);
|
585 | 591 | }
|
586 | 592 |
|
| 593 | + @Test |
| 594 | + public void testHeadersAnnotation() throws Exception { |
| 595 | + template.setDefaultTopic("headerMapTopic"); |
| 596 | + |
| 597 | + template.send(new GenericMessage<>("message1", Collections.emptyMap())); |
| 598 | + Awaitility.await().untilAsserted(() -> { |
| 599 | + assertThat(this.headerMapListener.invocationCount.get()).isEqualTo(1); |
| 600 | + }); |
| 601 | + assertThat(this.headerMapListener.text).isEqualTo("message1"); |
| 602 | + assertThat(this.headerMapListener.headers) |
| 603 | + .isNotNull() |
| 604 | + .containsOnlyKeys( |
| 605 | + "kafka_offset", |
| 606 | + "kafka_consumer", |
| 607 | + "kafka_timestampType", |
| 608 | + "kafka_receivedPartitionId", |
| 609 | + "kafka_receivedTopic", |
| 610 | + "kafka_receivedTimestamp", |
| 611 | + "kafka_groupId"); |
| 612 | + |
| 613 | + template.send(new GenericMessage<>("message2", |
| 614 | + Map.of("akey", "avalue", |
| 615 | + "bkey", "bvalue"))); |
| 616 | + Awaitility.await().untilAsserted(() -> { |
| 617 | + assertThat(this.headerMapListener.invocationCount.get()).isEqualTo(2); |
| 618 | + }); |
| 619 | + assertThat(this.headerMapListener.text).isEqualTo("message2"); |
| 620 | + assertThat(this.headerMapListener.headers) |
| 621 | + .isNotNull() |
| 622 | + .containsOnlyKeys( |
| 623 | + "kafka_offset", |
| 624 | + "kafka_consumer", |
| 625 | + "kafka_timestampType", |
| 626 | + "kafka_receivedPartitionId", |
| 627 | + "kafka_receivedTopic", |
| 628 | + "kafka_receivedTimestamp", |
| 629 | + "kafka_groupId", |
| 630 | + "akey", |
| 631 | + "bkey") |
| 632 | + .contains( |
| 633 | + Map.entry("akey", "avalue"), |
| 634 | + Map.entry("bkey", "bvalue")); |
| 635 | + } |
| 636 | + |
587 | 637 | @Test
|
588 | 638 | public void testMultiValidateNoDefaultHandler() throws Exception {
|
589 | 639 | this.kafkaJsonTemplate.setDefaultTopic("annotated40");
|
@@ -1545,6 +1595,11 @@ public MultiJsonListenerBean multiJsonListener() {
|
1545 | 1595 | return new MultiJsonListenerBean();
|
1546 | 1596 | }
|
1547 | 1597 |
|
| 1598 | + @Bean |
| 1599 | + public HeaderMapListenerBean headerMapListener() { |
| 1600 | + return new HeaderMapListenerBean(); |
| 1601 | + } |
| 1602 | + |
1548 | 1603 | @Bean
|
1549 | 1604 | public MultiListenerNoDefault multiNoDefault() {
|
1550 | 1605 | return new MultiListenerNoDefault();
|
@@ -2742,6 +2797,24 @@ public void defaultHandler(Bar bar) {
|
2742 | 2797 |
|
2743 | 2798 | }
|
2744 | 2799 |
|
| 2800 | + @KafkaListener(id = "headerMap", topics = "headerMapTopic") |
| 2801 | + static class HeaderMapListenerBean { |
| 2802 | + |
| 2803 | + final AtomicInteger invocationCount = new AtomicInteger(); |
| 2804 | + |
| 2805 | + private String text; |
| 2806 | + |
| 2807 | + private Map<String, Object> headers; |
| 2808 | + |
| 2809 | + @KafkaHandler(isDefault = true) |
| 2810 | + public void defaultHandler(@Payload String text, @Headers Map<String, Object> headers) { |
| 2811 | + this.text = text; |
| 2812 | + this.headers = headers; |
| 2813 | + this.invocationCount.incrementAndGet(); |
| 2814 | + } |
| 2815 | + |
| 2816 | + } |
| 2817 | + |
2745 | 2818 | @KafkaListener(id = "multiNoDefault", topics = "annotated40", containerFactory = "kafkaJsonListenerContainerFactory2")
|
2746 | 2819 | static class MultiListenerNoDefault {
|
2747 | 2820 |
|
|
0 commit comments