19

I have some configurations in my application.properties file:

...
quarkus.datasource.url=jdbc:postgresql://...:5432/....
quarkus.datasource.driver=org.postgresql.Driver
quarkus.datasource.username=user
quarkus.datasource.password=password
quarkus.hibernate-orm.database.generation=update
...

I have a scheduler with a @Transactional method that takes a long time to finish executing:

@ApplicationScoped
class MyScheduler {

...

    @Transactional
    @Scheduled(every = "7200s")
    open fun process() {

        ... my slow proccess goes here...
        entityManager.persist(myObject)

    }
}

And then, the transactional method receives a timeout error like that:

2019-06-24 20:11:59,874 WARN  [com.arj.ats.arjuna] (Transaction Reaper) ARJUNA012117: TransactionReaper::check timeout for TX 0:ffff0a000020:d58d:5cdad26e:81 in state  RUN

2019-06-24 20:12:47,198 WARN  [com.arj.ats.arjuna] (DefaultQuartzScheduler_Worker-3) ARJUNA012077: Abort called on already aborted atomic action 0:ffff0a000020:d58d:5cdad26e:81

Caused by: javax.transaction.RollbackException: ARJUNA016102: The transaction is not active! Uid is 0:ffff0a000020:d58d:5cdad26e:81

I believe that I must increase the timeout of my transacional method. But I dont know how I can do this.

Someone could help me, please?

Thanks!

Renan Vaz
  • 305
  • 1
  • 3
  • 8

4 Answers4

17

Seems that this has changed -> it is now possible to set the Transaction timeout:

https://quarkus.io/guides/transaction

You can configure the default transaction timeout, the timeout that applies to all transactions managed by the transaction manager, via the property:

quarkus.transaction-manager.default-transaction-timeout = 240s

-> specified as a duration (java.time.Duration format). Default is 60 sec

max
  • 1,134
  • 10
  • 16
9

Quarkus don't allow you to globally configure the default transaction timeout yet (see https://github.com/quarkusio/quarkus/pull/2984).

But you should be able to do this at the user transaction level.

You can inject the UserTransaction object and set the transaction timeout in a postconstruct bloc.

Something like this should work :

@ApplicationScoped
class MyScheduler {

    @Inject UserTransaction userTransaction;

    @PostConstruct
    fun init() {
        //set a timeout as high as you need
        userTransaction.setTransactionTimeout(3600);
    }

    @Transactional
    @Scheduled(every = "7200s")
    open fun process() {
        entityManager.persist(myObject)

    }
}

If you extract the code that make the transaction inside a Service, you can have a service with a @Transactional annotation, inject the UserTransaction in your scheduler and set the transaction timeout before calling the service.

All this works, I just tested both solution ;)

loicmathieu
  • 5,181
  • 26
  • 31
5

Use the @TransactionConfiguration annotation and specify the seconds:

@Transactional
@TransactionConfiguration(timeout = 9876)
@Scheduled(every = "7200s")
open fun process() {

    ... my slow proccess goes here...
    entityManager.persist(myObject)

}
bebbo
  • 2,830
  • 1
  • 32
  • 37
  • 1
    Here the link to the docs: https://quarkus.io/guides/transaction#transaction-configuration – max Sep 21 '22 at 17:53
3

Thanks @loicmathieu for the answer!

I will just append some more details below.

You need to remove @Transactional and set transaction timeout before begin the transaction. In the end, you must commit the transaction:

import io.quarkus.scheduler.Scheduled
import javax.enterprise.context.ApplicationScoped
import javax.inject.Inject
import javax.transaction.UserTransaction

@ApplicationScoped
open class MyScheduler {

    @Inject
    lateinit var em: EntityManager

    @Inject
    lateinit var ut: UserTransaction

    @Scheduled(every = "3600s")
    open fun process() {

        ut.setTransactionTimeout(3600)
        ut.begin()
        offerService.processOffers()
        ut.commit()
    }
}
Renan Vaz
  • 305
  • 1
  • 3
  • 8
  • You're right, I updated my answer with two working solutions that still allow you to use the @Transactional annotation to have automatic transaction support. Because your implementation is too naive as it didn't implements rollback and a proper error handling. – loicmathieu Jun 26 '19 at 14:55