I have a transactional method which has a fixed timeout. Is there a way to make a transaction timeout configurable through i.e. an application.yml
?
@Transactional(propagation = Propagation.REQUIRED, timeout = TIMEOUT)
public String doStuff(String id) throws Exception {
service.doSomeStuff
}
As we cannot assign variable value to Java annotation attribute , to programmatically set @Transactional
's timeout
, your best bet is to override AbstractPlatformTransactionManager#determineTimeout()
.
Suppose you are using JpaTransactionManager
, the new manager looks like the code below. It allows to set timeout per transaction. We can use TransactionDefinition
's name to identify a transaction ,which in case of Spring declarative transaction ,the default name is in the format of FullyQualifiedClassName.MethodName
.
public class FooTransactionManager extends JpaTransactionManager {
private Map<String, Integer> txTimeout = new HashMap<String, Integer>();
public <T> void configureTxTimeout(Class<T> clazz, String methodName, Integer timeoutSecond) {
txTimeout.put(clazz.getName() + "." + methodName, timeoutSecond);
}
//The timeout set by `configureTxTimeout` will have higher priority than the one set in @Transactional
@Override
protected int determineTimeout(TransactionDefinition definition) {;
if (txTimeout.containsKey(definition.getName())) {
return txTimeout.get(definition.getName());
} else {
return super.determineTimeout(definition);
}
}
}
Then configure the PlatformTransactionManager
:
@Bean
public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) {
final FooTransactionManager transactionManager = new FooTransactionManager();
transactionManager.setEntityManagerFactory(emf);
transactionManager.configureTxTimeout(Foo.class, "doStuff", 10);
transactionManager.configureTxTimeout(Bar.class, "doStuff", 20);
transactionManager.configureTxTimeout(Bar.class, "doMoreStuff", 30);
//blablabla
return transactionManager;
}
The codes above is just for demonstration purpose . In reality , you can use @Value
to read the value from an external properties (e.g application.yml
) during the configuration.
Update On 25-Jun-2020 :