4747import org .junit .runner .RunWith ;
4848import org .mockito .Mockito ;
4949
50+ import org .springframework .beans .factory .ObjectProvider ;
5051import org .springframework .beans .factory .annotation .Autowired ;
5152import org .springframework .context .annotation .Bean ;
5253import org .springframework .context .annotation .Configuration ;
54+ import org .springframework .context .annotation .Primary ;
5355import org .springframework .context .event .EventListener ;
5456import org .springframework .context .support .PropertySourcesPlaceholderConfigurer ;
5557import org .springframework .core .convert .converter .Converter ;
8890import org .springframework .kafka .test .EmbeddedKafkaBroker ;
8991import org .springframework .kafka .test .rule .EmbeddedKafkaRule ;
9092import 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 ;
9196import org .springframework .lang .NonNull ;
9297import org .springframework .messaging .Message ;
9398import org .springframework .messaging .MessageHeaders ;
@@ -173,6 +178,9 @@ public class EnableKafkaIntegrationTests {
173178 @ Autowired
174179 private FooConverter fooConverter ;
175180
181+ @ Autowired
182+ private ConcurrentKafkaListenerContainerFactory <Integer , String > transactionalFactory ;
183+
176184 @ Test
177185 public void testAnonymous () {
178186 MessageListenerContainer container = this .registry
@@ -669,6 +677,12 @@ public void testReceivePollResults() throws Exception {
669677 assertThat (this .listener .consumerRecords .iterator ().next ().value ()).isEqualTo ("allRecords" );
670678 }
671679
680+ @ Test
681+ public void testAutoConfigTm () {
682+ assertThat (this .transactionalFactory .getContainerProperties ().getTransactionManager ())
683+ .isInstanceOf (ChainedKafkaTransactionManager .class );
684+ }
685+
672686 @ Configuration
673687 @ EnableKafka
674688 @ EnableTransactionManagement (proxyTargetClass = true )
@@ -686,11 +700,23 @@ public PlatformTransactionManager transactionManager() {
686700 return Mockito .mock (PlatformTransactionManager .class );
687701 }
688702
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+
689714 private Throwable globalErrorThrowable ;
690715
691716 @ Bean
692717 public KafkaListenerContainerFactory <ConcurrentMessageListenerContainer <Integer , String >>
693- kafkaListenerContainerFactory () {
718+ kafkaListenerContainerFactory () {
719+
694720 ConcurrentKafkaListenerContainerFactory <Integer , String > factory =
695721 new ConcurrentKafkaListenerContainerFactory <>();
696722 factory .setConsumerFactory (consumerFactory ());
@@ -705,10 +731,25 @@ public PlatformTransactionManager transactionManager() {
705731
706732 @ Bean
707733 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+
709746 ConcurrentKafkaListenerContainerFactory <Integer , String > factory =
710747 new ConcurrentKafkaListenerContainerFactory <>();
711748 factory .setConsumerFactory (consumerFactory ());
749+ KafkaAwareTransactionManager <Integer , String > ktm = tm .getIfUnique ();
750+ if (ktm != null ) {
751+ factory .getContainerProperties ().setTransactionManager (ktm );
752+ }
712753 return factory ;
713754 }
714755
@@ -926,6 +967,13 @@ public ProducerFactory<Integer, String> producerFactory() {
926967 return new DefaultKafkaProducerFactory <>(producerConfigs ());
927968 }
928969
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+
929977 @ Bean
930978 public Map <String , Object > producerConfigs () {
931979 return KafkaTestUtils .producerProps (embeddedKafka );
@@ -1481,7 +1529,7 @@ public void listen(String foo) {
14811529 }
14821530
14831531 @ KafkaListener (id = "ifctx" , topics = "annotated9" )
1484- @ Transactional
1532+ @ Transactional ( transactionManager = "transactionManager" )
14851533 public void listenTx (String foo ) {
14861534 latch2 .countDown ();
14871535 }
0 commit comments