@@ -226,7 +226,7 @@ public List<PartitionInfo> partitionsFor(String topic) {
226
226
return producer .partitionsFor (topic );
227
227
}
228
228
finally {
229
- closeProducer (producer , inTransaction ());
229
+ closeProducer (producer , inLocalTransaction ());
230
230
}
231
231
}
232
232
@@ -237,7 +237,7 @@ public List<PartitionInfo> partitionsFor(String topic) {
237
237
return producer .metrics ();
238
238
}
239
239
finally {
240
- closeProducer (producer , inTransaction ());
240
+ closeProducer (producer , inLocalTransaction ());
241
241
}
242
242
}
243
243
@@ -248,7 +248,7 @@ public <T> T execute(ProducerCallback<K, V, T> callback) {
248
248
return callback .doInKafka (producer );
249
249
}
250
250
finally {
251
- closeProducer (producer , inTransaction ());
251
+ closeProducer (producer , inLocalTransaction ());
252
252
}
253
253
}
254
254
@@ -295,7 +295,7 @@ public void flush() {
295
295
producer .flush ();
296
296
}
297
297
finally {
298
- closeProducer (producer , inTransaction ());
298
+ closeProducer (producer , inLocalTransaction ());
299
299
}
300
300
}
301
301
@@ -328,12 +328,20 @@ protected void closeProducer(Producer<K, V> producer, boolean inLocalTx) {
328
328
* @return a Future for the {@link RecordMetadata}.
329
329
*/
330
330
protected ListenableFuture <SendResult <K , V >> doSend (final ProducerRecord <K , V > producerRecord ) {
331
+ if (this .transactional ) {
332
+ Assert .state (inTransaction (),
333
+ "No transaction is in process; "
334
+ + "possible solutions: run the template operation within the scope of a "
335
+ + "template.executeInTransaction() operation, start a transaction with @Transactional "
336
+ + "before invoking the template method, "
337
+ + "run in a transaction started by a listener container when consuming a record" );
338
+ }
331
339
final Producer <K , V > producer = getTheProducer ();
332
340
if (this .logger .isTraceEnabled ()) {
333
341
this .logger .trace ("Sending: " + producerRecord );
334
342
}
335
343
final SettableListenableFuture <SendResult <K , V >> future = new SettableListenableFuture <>();
336
- final boolean inLocalTx = inTransaction ();
344
+ final boolean inLocalTx = inLocalTransaction ();
337
345
producer .send (producerRecord , new Callback () {
338
346
339
347
@ Override
@@ -365,8 +373,8 @@ public void onCompletion(RecordMetadata metadata, Exception exception) {
365
373
}
366
374
}
367
375
finally {
368
- if (KafkaTemplate .this .producers . get () == null ) {
369
- closeProducer (producer , inLocalTx );
376
+ if (! KafkaTemplate .this .transactional ) {
377
+ closeProducer (producer , false );
370
378
}
371
379
}
372
380
}
@@ -381,8 +389,15 @@ public void onCompletion(RecordMetadata metadata, Exception exception) {
381
389
return future ;
382
390
}
383
391
392
+
384
393
protected boolean inTransaction () {
385
- return this .producers .get () != null || TransactionSynchronizationManager .isActualTransactionActive ();
394
+ return this .transactional && (this .producers .get () != null
395
+ || TransactionSynchronizationManager .getResource (this .producerFactory ) != null
396
+ || TransactionSynchronizationManager .isActualTransactionActive ());
397
+ }
398
+
399
+ protected boolean inLocalTransaction () {
400
+ return this .transactional && this .producers .get () != null ;
386
401
}
387
402
388
403
private Producer <K , V > getTheProducer () {
0 commit comments