47
47
import org .junit .runner .RunWith ;
48
48
import org .mockito .Mockito ;
49
49
50
+ import org .springframework .beans .factory .ObjectProvider ;
50
51
import org .springframework .beans .factory .annotation .Autowired ;
51
52
import org .springframework .context .annotation .Bean ;
52
53
import org .springframework .context .annotation .Configuration ;
54
+ import org .springframework .context .annotation .Primary ;
53
55
import org .springframework .context .event .EventListener ;
54
56
import org .springframework .context .support .PropertySourcesPlaceholderConfigurer ;
55
57
import org .springframework .core .convert .converter .Converter ;
88
90
import org .springframework .kafka .test .EmbeddedKafkaBroker ;
89
91
import org .springframework .kafka .test .rule .EmbeddedKafkaRule ;
90
92
import org .springframework .kafka .test .utils .KafkaTestUtils ;
93
+ import org .springframework .kafka .transaction .ChainedKafkaTransactionManager ;
94
+ import org .springframework .kafka .transaction .KafkaAwareTransactionManager ;
95
+ import org .springframework .kafka .transaction .KafkaTransactionManager ;
91
96
import org .springframework .lang .NonNull ;
92
97
import org .springframework .messaging .Message ;
93
98
import org .springframework .messaging .MessageHeaders ;
@@ -173,6 +178,9 @@ public class EnableKafkaIntegrationTests {
173
178
@ Autowired
174
179
private FooConverter fooConverter ;
175
180
181
+ @ Autowired
182
+ private ConcurrentKafkaListenerContainerFactory <Integer , String > transactionalFactory ;
183
+
176
184
@ Test
177
185
public void testAnonymous () {
178
186
MessageListenerContainer container = this .registry
@@ -669,6 +677,12 @@ public void testReceivePollResults() throws Exception {
669
677
assertThat (this .listener .consumerRecords .iterator ().next ().value ()).isEqualTo ("allRecords" );
670
678
}
671
679
680
+ @ Test
681
+ public void testAutoConfigTm () {
682
+ assertThat (this .transactionalFactory .getContainerProperties ().getTransactionManager ())
683
+ .isInstanceOf (ChainedKafkaTransactionManager .class );
684
+ }
685
+
672
686
@ Configuration
673
687
@ EnableKafka
674
688
@ EnableTransactionManagement (proxyTargetClass = true )
@@ -686,11 +700,23 @@ public PlatformTransactionManager transactionManager() {
686
700
return Mockito .mock (PlatformTransactionManager .class );
687
701
}
688
702
703
+ @ Bean
704
+ public KafkaTransactionManager <Integer , String > ktm () {
705
+ return new KafkaTransactionManager <>(txProducerFactory ());
706
+ }
707
+
708
+ @ Bean
709
+ @ Primary
710
+ public ChainedKafkaTransactionManager <Integer , String > cktm () {
711
+ return new ChainedKafkaTransactionManager <>(ktm (), transactionManager ());
712
+ }
713
+
689
714
private Throwable globalErrorThrowable ;
690
715
691
716
@ Bean
692
717
public KafkaListenerContainerFactory <ConcurrentMessageListenerContainer <Integer , String >>
693
- kafkaListenerContainerFactory () {
718
+ kafkaListenerContainerFactory () {
719
+
694
720
ConcurrentKafkaListenerContainerFactory <Integer , String > factory =
695
721
new ConcurrentKafkaListenerContainerFactory <>();
696
722
factory .setConsumerFactory (consumerFactory ());
@@ -705,10 +731,25 @@ public PlatformTransactionManager transactionManager() {
705
731
706
732
@ Bean
707
733
public KafkaListenerContainerFactory <ConcurrentMessageListenerContainer <Integer , String >>
708
- withNoReplyTemplateContainerFactory () {
734
+ withNoReplyTemplateContainerFactory () {
735
+
736
+ ConcurrentKafkaListenerContainerFactory <Integer , String > factory =
737
+ new ConcurrentKafkaListenerContainerFactory <>();
738
+ factory .setConsumerFactory (consumerFactory ());
739
+ return factory ;
740
+ }
741
+
742
+ @ Bean
743
+ public KafkaListenerContainerFactory <ConcurrentMessageListenerContainer <Integer , String >>
744
+ transactionalFactory (ObjectProvider <KafkaAwareTransactionManager <Integer , String >> tm ) {
745
+
709
746
ConcurrentKafkaListenerContainerFactory <Integer , String > factory =
710
747
new ConcurrentKafkaListenerContainerFactory <>();
711
748
factory .setConsumerFactory (consumerFactory ());
749
+ KafkaAwareTransactionManager <Integer , String > ktm = tm .getIfUnique ();
750
+ if (ktm != null ) {
751
+ factory .getContainerProperties ().setTransactionManager (ktm );
752
+ }
712
753
return factory ;
713
754
}
714
755
@@ -926,6 +967,13 @@ public ProducerFactory<Integer, String> producerFactory() {
926
967
return new DefaultKafkaProducerFactory <>(producerConfigs ());
927
968
}
928
969
970
+ @ Bean
971
+ public ProducerFactory <Integer , String > txProducerFactory () {
972
+ DefaultKafkaProducerFactory <Integer , String > pf = new DefaultKafkaProducerFactory <>(producerConfigs ());
973
+ pf .setTransactionIdPrefix ("tx-" );
974
+ return pf ;
975
+ }
976
+
929
977
@ Bean
930
978
public Map <String , Object > producerConfigs () {
931
979
return KafkaTestUtils .producerProps (embeddedKafka );
@@ -1481,7 +1529,7 @@ public void listen(String foo) {
1481
1529
}
1482
1530
1483
1531
@ KafkaListener (id = "ifctx" , topics = "annotated9" )
1484
- @ Transactional
1532
+ @ Transactional ( transactionManager = "transactionManager" )
1485
1533
public void listenTx (String foo ) {
1486
1534
latch2 .countDown ();
1487
1535
}
0 commit comments