I have an app that consumes from Kafka and perform upsert to Postgres like the following:
@Incoming("sink")
@Transactional
public CompletionStage<Void> sink(KafkaRecordBatch<String, String> messages)
{
persist(messages);
return messages.ack();
}
Within persist() i have the following:
entityManager.createNativeQuery(sql);
According to the Kafka Doc, @Transactional will make the operation Blocking, but the log is saying there are multiple threads active within it and it's causing the app to crash with "Enlisted connection used without active transaction". I am using the following dependencies:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-reactive-messaging-kafka</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency>
Stacktrace:
2023-06-17 00:35:14,618 WARN [com.arj.ats.arjuna] (executor-thread-0) ARJUNA012094: Commit of action id 0:ffff0a020cc2:9e77:648cfdd7:96f0 invoked while multiple threads active within it.
2023-06-17 00:35:14,619 WARN [com.arj.ats.arjuna] (executor-thread-0) ARJUNA012107: CheckedAction::check - atomic action 0:ffff0a020cc2:9e77:648cfdd7:96f0 commiting with 2 threads active!
2023-06-17 00:35:14,621 WARN [com.arj.ats.jta] (executor-thread-0) ARJUNA016039: onePhaseCommit on < formatId=131077, gtrid_length=35, bqual_length=36, tx_uid=0:ffff0a020cc2:9e77:648cfdd7:96f0, node_name=quarkus, branch_uid=0:ffff0a020cc2:9e77:648cfdd7:96f3, subordinatenodename=null, eis_name=0 > (io.agroal.narayana.LocalXAResource@123fb291) failed with exception XAException.XA_RBROLLBACK: javax.transaction.xa.XAException: Error trying to transactionCommit local transaction: Enlisted connection used without active transaction
at io.agroal.narayana.LocalXAResource.xaException(LocalXAResource.java:140)
at io.agroal.narayana.LocalXAResource.xaException(LocalXAResource.java:134)
at io.agroal.narayana.LocalXAResource.commit(LocalXAResource.java:72)
at com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord.topLevelOnePhaseCommit(XAResourceRecord.java:702)
at com.arjuna.ats.arjuna.coordinator.BasicAction.onePhaseCommit(BasicAction.java:2400)
at com.arjuna.ats.arjuna.coordinator.BasicAction.End(BasicAction.java:1502)
at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:96)
at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162)
at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1295)
at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:128)
at io.quarkus.narayana.jta.runtime.NotifyingTransactionManager.commit(NotifyingTransactionManager.java:70)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.endTransaction(TransactionalInterceptorBase.java:374)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.lambda$handleAsync$2(TransactionalInterceptorBase.java:232)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.doInTransaction(TransactionalInterceptorBase.java:292)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.lambda$handleAsync$3(TransactionalInterceptorBase.java:229)
at io.smallrye.context.impl.wrappers.SlowContextualBiFunction.apply(SlowContextualBiFunction.java:21)
at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:930)
at java.base/java.util.concurrent.CompletableFuture.uniHandleStage(CompletableFuture.java:946)
at java.base/java.util.concurrent.CompletableFuture.handle(CompletableFuture.java:2266)
at io.smallrye.context.CompletableFutureWrapper.handle(CompletableFutureWrapper.java:192)
at io.smallrye.context.CompletableFutureWrapper.handle(CompletableFutureWrapper.java:17)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.handleAsync(TransactionalInterceptorBase.java:227)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInOurTx(TransactionalInterceptorBase.java:155)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInOurTx(TransactionalInterceptorBase.java:104)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.doIntercept(TransactionalInterceptorRequired.java:38)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.intercept(TransactionalInterceptorBase.java:58)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.intercept(TransactionalInterceptorRequired.java:32)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired_Bean.intercept(Unknown Source)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:33)
at io.raft.commsbroker.KafkaConsumer_Subclass.postgresSink(Unknown Source)
at io.raft.commsbroker.KafkaConsumer_ClientProxy.postgresSink(Unknown Source)
at io.raft.commsbroker.KafkaConsumer_SmallRyeMessagingInvoker_postgresSink_6a10f16244d6587e6bd4daab44689ece2587e1b7.invoke(Unknown Source)
at io.smallrye.reactive.messaging.providers.AbstractMediator.lambda$invokeBlocking$4(AbstractMediator.java:125)
at io.smallrye.context.impl.wrappers.SlowContextualConsumer.accept(SlowContextualConsumer.java:21)
at io.smallrye.mutiny.operators.uni.builders.UniCreateWithEmitter.subscribe(UniCreateWithEmitter.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromDeferredSupplier.subscribe(UniCreateFromDeferredSupplier.java:36)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:52)
at io.smallrye.mutiny.groups.UniSubscribe.with(UniSubscribe.java:112)
at io.smallrye.mutiny.groups.UniSubscribe.with(UniSubscribe.java:89)
at io.vertx.mutiny.core.Context$1.handle(Context.java:170)
at io.vertx.mutiny.core.Context$1.handle(Context.java:168)
at io.vertx.core.impl.ContextBase.lambda$null$0(ContextBase.java:137)
at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:264)
at io.vertx.core.impl.ContextBase.lambda$executeBlocking$1(ContextBase.java:135)
at io.vertx.core.impl.TaskQueue.run(TaskQueue.java:76)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.sql.SQLException: Enlisted connection used without active transaction
at io.agroal.pool.ConnectionHandler.verifyEnlistment(ConnectionHandler.java:398)
at io.agroal.pool.ConnectionHandler.transactionCommit(ConnectionHandler.java:355)
at io.agroal.narayana.LocalXAResource.commit(LocalXAResource.java:69)
... 53 more