38
38
import org .apache .kafka .clients .consumer .ConsumerConfig ;
39
39
import org .apache .kafka .clients .consumer .ConsumerRecord ;
40
40
import org .apache .kafka .clients .consumer .ConsumerRecords ;
41
+ import org .apache .kafka .clients .consumer .OffsetAndMetadata ;
41
42
import org .apache .kafka .clients .producer .Callback ;
42
43
import org .apache .kafka .clients .producer .MockProducer ;
43
44
import org .apache .kafka .clients .producer .Producer ;
44
45
import org .apache .kafka .clients .producer .ProducerConfig ;
45
46
import org .apache .kafka .clients .producer .ProducerRecord ;
47
+ import org .apache .kafka .common .TopicPartition ;
46
48
import org .apache .kafka .common .serialization .StringDeserializer ;
47
49
import org .apache .kafka .common .serialization .StringSerializer ;
48
50
import org .assertj .core .api .Assertions ;
@@ -77,10 +79,13 @@ public class KafkaTemplateTransactionTests {
77
79
78
80
private static final String STRING_KEY_TOPIC = "stringKeyTopic" ;
79
81
82
+ private static final String LOCAL_TX_IN_TOPIC = "localTxInTopic" ;
83
+
80
84
@ 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" );
84
89
85
90
@ Test
86
91
public void testLocalTransaction () throws Exception {
@@ -93,13 +98,22 @@ public void testLocalTransaction() throws Exception {
93
98
template .setDefaultTopic (STRING_KEY_TOPIC );
94
99
Map <String , Object > consumerProps = KafkaTestUtils .consumerProps ("testTxString" , "false" , embeddedKafka );
95
100
consumerProps .put (ConsumerConfig .AUTO_OFFSET_RESET_CONFIG , "earliest" );
101
+ consumerProps .put (ConsumerConfig .ISOLATION_LEVEL_CONFIG , "read_committed" );
96
102
DefaultKafkaConsumerFactory <String , String > cf = new DefaultKafkaConsumerFactory <>(consumerProps );
97
103
cf .setKeyDeserializer (new StringDeserializer ());
98
104
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 );
100
108
template .executeInTransaction (t -> {
101
109
t .sendDefault ("foo" , "bar" );
102
110
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" );
103
117
return null ;
104
118
});
105
119
ConsumerRecords <String , String > records = KafkaTestUtils .getRecords (consumer );
@@ -112,6 +126,8 @@ public void testLocalTransaction() throws Exception {
112
126
}
113
127
record = iterator .next ();
114
128
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 );
115
131
consumer .close ();
116
132
assertThat (KafkaTestUtils .getPropertyValue (pf , "cache" , BlockingQueue .class ).size ()).isEqualTo (1 );
117
133
pf .destroy ();
@@ -210,8 +226,8 @@ public void testNoTx() {
210
226
KafkaTemplate <String , String > template = new KafkaTemplate <>(pf );
211
227
template .setDefaultTopic (STRING_KEY_TOPIC );
212
228
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;" );
215
231
}
216
232
217
233
@ Test
0 commit comments