micronaut-data: javax.transaction.Transactional does not work at the individual method level
Expected Behavior
That methods carrying the javax.transaction.Transactional annotation run in a transaction with a configuration matching the parameters specified in the annotation and that methods not carrying the javax.transaction.Transactional successfully run outside a transaction context.
javax.transaction.Transactional is clearly intended to be a method level annotation, so it must be possible to non-transactional methods on a class.
Actual Behaviour
Methods not carrying the javax.transaction.Transactional annotation fail with:
io.micronaut.transaction.exceptions.NoTransactionException: No current transaction present. Consider declaring @Transactional on the surrounding method
Steps To Reproduce
As an example, I modified the test case: data-tx:io.micronaut.transaction.jdbc.TransactionAnnotationSpec as follows:
dhcp-10-39-204-9:data-tx GK4J0B$ git diff
diff --git a/data-tx/src/test/groovy/io/micronaut/transaction/jdbc/TransactionAnnotationSpec.groovy b/data-tx/src/test/groovy/io/micronaut/transaction/jdbc/TransactionAnnotationSpec.groovy
index 86bf641a3..5d8510202 100644
--- a/data-tx/src/test/groovy/io/micronaut/transaction/jdbc/TransactionAnnotationSpec.groovy
+++ b/data-tx/src/test/groovy/io/micronaut/transaction/jdbc/TransactionAnnotationSpec.groovy
@@ -60,6 +60,11 @@ class TransactionAnnotationSpec extends Specification {
testService.readTransactionally() == 2
testService.lastEvent
+ when:"A non-transactional method is called"
+ def z = testService.readNonTransactionally()
+
+ then:
+ z == 2
when:"Test that connections are never exhausted"
int i = 0
@@ -133,6 +138,19 @@ class TransactionAnnotationSpec extends Specification {
}
+ int readNonTransactionally() {
+ def ps2 = connection.prepareStatement("select count(*) as count from book")
+ def rs = ps2.executeQuery()
+ try {
+ rs.next()
+ rs.getInt("count")
+ } finally {
+ ps2.close()
+ rs.close()
+ }
+
+ }
+
and get this when running:
io.micronaut.transaction.exceptions.NoTransactionException: No current transaction present. Consider declaring @Transactional on the surrounding method
at app//io.micronaut.transaction.jdbc.TransactionalConnectionInterceptor.intercept(TransactionalConnectionInterceptor.java:65)
at app//io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:137)
at app//io.micronaut.transaction.jdbc.TransactionAnnotationSpec$TestService.readNonTransactionally(TransactionAnnotationSpec.groovy:142)
at io.micronaut.transaction.jdbc.TransactionAnnotationSpec.test transactional annotation handling(TransactionAnnotationSpec.groovy:64)
Caused by: io.micronaut.transaction.jdbc.exceptions.CannotGetJdbcConnectionException: No current JDBC Connection found. Consider wrapping this call in transactional boundaries.
at app//io.micronaut.transaction.jdbc.DataSourceUtils.doGetConnection(DataSourceUtils.java:135)
at app//io.micronaut.transaction.jdbc.DataSourceUtils.getConnection(DataSourceUtils.java:93)
at app//io.micronaut.transaction.jdbc.TransactionalConnectionInterceptor.intercept(TransactionalConnectionInterceptor.java:63)
... 3 more
Environment Information
Mac OS JDK 11
Example Application
No response
Version
micronaut parent 3.2.1, but I tried version 3.2.7 of the parent and got the same result
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 24 (12 by maintainers)
@matt-snider Given that annotating the non-transactional methods with io.micronaut.transaction.annotation.ReadOnly avoids this trouble, it shows that spring tx like behavior is possible using native micronaut tx. My suggestion for a solution would be to have methods on transactional classes that don’t carry @Transactional see behavior that equivalent to what they get if annotated with @ReadOnly. In other words, transactional behavior should apply only to methods that have declared their desire for it by being annotated with @Transactional.