oscerd commented on code in PR #26523:
URL: https://github.com/apache/camel/pull/26523#discussion_r4029169975


##########
components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaProducer.java:
##########
@@ -518,8 +521,11 @@ private void startKafkaTransaction(Exchange exchange) {
 
         if (!uow.isTransactedBy(transactionId)) {
             LOG.debug("Starting kafka transaction {} with exchange {}", 
transactionId, exchange.getExchangeId());
-            uow.beginTransactedBy(transactionId);
+            // Begin the broker transaction first, then mark the unit of work 
and register the
+            // synchronization. This way a failure in beginTransaction() does 
not leave the unit of work
+            // flagged as transacted without a synchronization to commit or 
roll it back (CAMEL-24780).
             kafkaProducer.beginTransaction();
+            uow.beginTransactedBy(transactionId);
             uow.addSynchronization(new 
KafkaTransactionSynchronization(transactionId, kafkaProducer));

Review Comment:
   Thanks — I'm leaving this as-is. The window is between two in-memory 
operations (`beginTransactedBy` adds to a set, `addSynchronization` adds to a 
list) that don't throw under normal operation; the only realistic trigger is a 
JVM-level error such as `OutOfMemoryError`, in which case the follow-up 
`abortTransaction()` broker call would almost certainly fail too. Wrapping it 
adds nesting for a path that can't meaningfully recover, so I'd rather keep the 
three-step sequence readable.
   
   _Claude Code on behalf of @oscerd_
   



##########
components/camel-kafka/src/test/java/org/apache/camel/component/kafka/KafkaProducerTest.java:
##########
@@ -189,6 +192,39 @@ public void processAsyncSendsMessageWithException() {
         assertRecordMetadataExists();
     }
 
+    @Test
+    public void processAsyncCompletesCallbackWhenBeginTransactionFails() 
throws Exception {
+        // CAMEL-24780: a failure to begin the transaction must set the 
exception and complete the async
+        // callback rather than escaping process(), and it must not leave the 
unit of work flagged as
+        // transacted without a synchronization to commit or roll it back.
+        setTransactionId(producer, "test-tx");
+        endpoint.getConfiguration().setTopic("sometopic");
+
+        Producer kp = producer.getKafkaProducer();
+        Mockito.doThrow(new ApiException("cannot 
begin")).when(kp).beginTransaction();
+
+        UnitOfWork uow = Mockito.mock(UnitOfWork.class);
+        Mockito.when(uow.isTransactedBy(any())).thenReturn(false);
+        Mockito.when(exchange.getUnitOfWork()).thenReturn(uow);
+        Mockito.when(exchange.getIn()).thenReturn(in);
+        Mockito.when(exchange.getMessage()).thenReturn(in);
+
+        boolean sync = producer.process(exchange, callback);
+
+        assertTrue(sync);
+        Mockito.verify(exchange).setException(isA(ApiException.class));
+        Mockito.verify(callback).done(eq(true));
+        // begin failed, so the unit of work must be left untouched (no 
dangling transacted flag)
+        Mockito.verify(uow, Mockito.never()).beginTransactedBy(any());
+        Mockito.verify(uow, Mockito.never()).addSynchronization(any());
+    }

Review Comment:
   The abort-on-send-failure path is handled by the existing Camel `UnitOfWork` 
lifecycle (the registered `KafkaTransactionSynchronization.onDone` → 
`abortTransaction()`), which this PR does not change — it's exercised by the 
transactional integration tests. Since it's pre-existing behavior rather than 
something introduced here, I've kept this PR focused on the begin-ordering fix. 
Happy to add dedicated `KafkaTransactionSynchronization` unit tests in a 
follow-up if that's useful.
   
   _Claude Code on behalf of @oscerd_
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to