3838import org .apache .kafka .clients .consumer .ConsumerConfig ;
3939import org .apache .kafka .clients .consumer .ConsumerRecord ;
4040import org .apache .kafka .clients .consumer .ConsumerRecords ;
41+ import org .apache .kafka .clients .consumer .OffsetAndMetadata ;
4142import org .apache .kafka .clients .producer .Callback ;
4243import org .apache .kafka .clients .producer .MockProducer ;
4344import org .apache .kafka .clients .producer .Producer ;
4445import org .apache .kafka .clients .producer .ProducerConfig ;
4546import org .apache .kafka .clients .producer .ProducerRecord ;
47+ import org .apache .kafka .common .TopicPartition ;
4648import org .apache .kafka .common .serialization .StringDeserializer ;
4749import org .apache .kafka .common .serialization .StringSerializer ;
4850import org .assertj .core .api .Assertions ;
@@ -77,10 +79,13 @@ public class KafkaTemplateTransactionTests {
7779
7880 private static final String STRING_KEY_TOPIC = "stringKeyTopic" ;
7981
82+ private static final String LOCAL_TX_IN_TOPIC = "localTxInTopic" ;
83+
8084 @ ClassRule
81- public static KafkaEmbedded embeddedKafka = new KafkaEmbedded (1 , true , STRING_KEY_TOPIC )
82- .brokerProperty (KafkaConfig .TransactionsTopicReplicationFactorProp (), "1" )
83- .brokerProperty (KafkaConfig .TransactionsTopicMinISRProp (), "1" );
85+ public static KafkaEmbedded embeddedKafka = new KafkaEmbedded (1 , true , STRING_KEY_TOPIC ,
86+ LOCAL_TX_IN_TOPIC )
87+ .brokerProperty (KafkaConfig .TransactionsTopicReplicationFactorProp (), "1" )
88+ .brokerProperty (KafkaConfig .TransactionsTopicMinISRProp (), "1" );
8489
8590 @ Test
8691 public void testLocalTransaction () throws Exception {
@@ -93,13 +98,22 @@ public void testLocalTransaction() throws Exception {
9398 template .setDefaultTopic (STRING_KEY_TOPIC );
9499 Map <String , Object > consumerProps = KafkaTestUtils .consumerProps ("testTxString" , "false" , embeddedKafka );
95100 consumerProps .put (ConsumerConfig .AUTO_OFFSET_RESET_CONFIG , "earliest" );
101+ consumerProps .put (ConsumerConfig .ISOLATION_LEVEL_CONFIG , "read_committed" );
96102 DefaultKafkaConsumerFactory <String , String > cf = new DefaultKafkaConsumerFactory <>(consumerProps );
97103 cf .setKeyDeserializer (new StringDeserializer ());
98104 Consumer <String , String > consumer = cf .createConsumer ();
99- embeddedKafka .consumeFromAnEmbeddedTopic (consumer , STRING_KEY_TOPIC );
105+ embeddedKafka .consumeFromAllEmbeddedTopics (consumer );
106+ template .executeInTransaction (kt -> kt .send (LOCAL_TX_IN_TOPIC , "one" ));
107+ ConsumerRecord <String , String > singleRecord = KafkaTestUtils .getSingleRecord (consumer , LOCAL_TX_IN_TOPIC );
100108 template .executeInTransaction (t -> {
101109 t .sendDefault ("foo" , "bar" );
102110 t .sendDefault ("baz" , "qux" );
111+ t .sendOffsetsToTransaction (Collections .singletonMap (
112+ new TopicPartition (LOCAL_TX_IN_TOPIC , singleRecord .partition ()),
113+ new OffsetAndMetadata (singleRecord .offset () + 1L )), "testLocalTx" );
114+ assertThat (KafkaTestUtils .getPropertyValue (
115+ KafkaTestUtils .getPropertyValue (template , "producers" , ThreadLocal .class ).get (),
116+ "delegate.transactionManager.transactionalId" )).isEqualTo ("my.transaction.0" );
103117 return null ;
104118 });
105119 ConsumerRecords <String , String > records = KafkaTestUtils .getRecords (consumer );
@@ -112,6 +126,8 @@ public void testLocalTransaction() throws Exception {
112126 }
113127 record = iterator .next ();
114128 assertThat (record ).has (Assertions .<ConsumerRecord <String , String >>allOf (key ("baz" ), value ("qux" )));
129+ // 2 log slots, 1 for the record, 1 for the commit
130+ assertThat (consumer .position (new TopicPartition (LOCAL_TX_IN_TOPIC , singleRecord .partition ()))).isEqualTo (2L );
115131 consumer .close ();
116132 assertThat (KafkaTestUtils .getPropertyValue (pf , "cache" , BlockingQueue .class ).size ()).isEqualTo (1 );
117133 pf .destroy ();
@@ -210,8 +226,8 @@ public void testNoTx() {
210226 KafkaTemplate <String , String > template = new KafkaTemplate <>(pf );
211227 template .setDefaultTopic (STRING_KEY_TOPIC );
212228 assertThatThrownBy (() -> template .send ("foo" , "bar" ))
213- .isInstanceOf (IllegalStateException .class )
214- .hasMessageContaining ("No transaction is in process;" );
229+ .isInstanceOf (IllegalStateException .class )
230+ .hasMessageContaining ("No transaction is in process;" );
215231 }
216232
217233 @ Test
0 commit comments