|
68 | 68 | import org.springframework.kafka.transaction.KafkaAwareTransactionManager;
|
69 | 69 | import org.springframework.lang.Nullable;
|
70 | 70 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
| 71 | +import org.springframework.transaction.PlatformTransactionManager; |
71 | 72 | import org.springframework.transaction.support.TransactionSynchronizationManager;
|
72 | 73 |
|
73 | 74 | /**
|
@@ -655,6 +656,77 @@ public void failure(ConsumerRecords records, Exception exception, Consumer consu
|
655 | 656 | }
|
656 | 657 | }
|
657 | 658 |
|
| 659 | + @Test |
| 660 | + @SuppressWarnings({ "rawtypes", "unchecked" }) |
| 661 | + void testInterceptInTxNonKafkaTM() throws InterruptedException { |
| 662 | + ConsumerFactory consumerFactory = mock(ConsumerFactory.class); |
| 663 | + final Consumer consumer = mock(Consumer.class); |
| 664 | + TopicPartition tp0 = new TopicPartition("foo", 0); |
| 665 | + ConsumerRecord record1 = new ConsumerRecord("foo", 0, 0L, "bar", "baz"); |
| 666 | + ConsumerRecords records = new ConsumerRecords( |
| 667 | + Collections.singletonMap(tp0, Collections.singletonList(record1))); |
| 668 | + ConsumerRecords empty = new ConsumerRecords(Collections.emptyMap()); |
| 669 | + AtomicInteger firstOrSecondPoll = new AtomicInteger(); |
| 670 | + willAnswer(invocation -> { |
| 671 | + Thread.sleep(10); |
| 672 | + return firstOrSecondPoll.incrementAndGet() < 2 ? records : empty; |
| 673 | + }).given(consumer).poll(any()); |
| 674 | + List<TopicPartition> assignments = Arrays.asList(tp0); |
| 675 | + willAnswer(invocation -> { |
| 676 | + ((ConsumerRebalanceListener) invocation.getArgument(1)) |
| 677 | + .onPartitionsAssigned(assignments); |
| 678 | + return null; |
| 679 | + }).given(consumer).subscribe(any(Collection.class), any()); |
| 680 | + given(consumer.position(any())).willReturn(0L); |
| 681 | + given(consumerFactory.createConsumer("grp", "", "-0", KafkaTestUtils.defaultPropertyOverrides())) |
| 682 | + .willReturn(consumer); |
| 683 | + ContainerProperties containerProperties = new ContainerProperties("foo"); |
| 684 | + containerProperties.setGroupId("grp"); |
| 685 | + AtomicReference<List<ConsumerRecord<String, String>>> received = new AtomicReference<>(); |
| 686 | + containerProperties.setMessageListener((MessageListener) rec -> { |
| 687 | + }); |
| 688 | + containerProperties.setMissingTopicsFatal(false); |
| 689 | + List<String> order = new ArrayList<>(); |
| 690 | + CountDownLatch latch = new CountDownLatch(2); |
| 691 | + PlatformTransactionManager tm = mock(PlatformTransactionManager.class); |
| 692 | + willAnswer(inv -> { |
| 693 | + order.add("tx"); |
| 694 | + latch.countDown(); |
| 695 | + return null; |
| 696 | + }).given(tm).getTransaction(any()); |
| 697 | + containerProperties.setTransactionManager(tm); |
| 698 | + ConcurrentMessageListenerContainer container = new ConcurrentMessageListenerContainer(consumerFactory, |
| 699 | + containerProperties); |
| 700 | + CountDownLatch successCalled = new CountDownLatch(1); |
| 701 | + container.setRecordInterceptor(new RecordInterceptor() { |
| 702 | + |
| 703 | + @Override |
| 704 | + @Nullable |
| 705 | + public ConsumerRecord intercept(ConsumerRecord rec, Consumer consumer) { |
| 706 | + order.add("interceptor"); |
| 707 | + latch.countDown(); |
| 708 | + return rec; |
| 709 | + } |
| 710 | + |
| 711 | + @Override |
| 712 | + public void success(ConsumerRecord record, Consumer consumer) { |
| 713 | + order.add("success"); |
| 714 | + successCalled.countDown(); |
| 715 | + } |
| 716 | + |
| 717 | + }); |
| 718 | + container.setInterceptBeforeTx(false); |
| 719 | + container.start(); |
| 720 | + try { |
| 721 | + assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue(); |
| 722 | + assertThat(successCalled.await(10, TimeUnit.SECONDS)).isTrue(); |
| 723 | + assertThat(order).containsExactly("tx", "interceptor", "success"); |
| 724 | + } |
| 725 | + finally { |
| 726 | + container.stop(); |
| 727 | + } |
| 728 | + } |
| 729 | + |
658 | 730 | @SuppressWarnings({ "rawtypes", "unchecked" })
|
659 | 731 | @Test
|
660 | 732 | void testNoCommitOnAssignmentWithEarliest() throws InterruptedException {
|
|
0 commit comments