micronaut-sql
micronaut-sql copied to clipboard
Outdated documentation for JDBC Transaction management
Expected Behavior
-
Create a new project using https://launch.micronaut.io. Default settings, but with
jdbc-hikari
added: -
Follow https://micronaut-projects.github.io/micronaut-sql/latest/guide/#jdbc to get transactions working.
Actual Behaviour
The docs are outdated around the "Using Spring Transaction Management" section.
Issue 1
Gradle is unable to resolve implementation("io.micronaut:micronaut-spring")
. I changed this to implementation("io.micronaut.spring:micronaut-spring-annotation")
, but not sure if this is correct as I don't have access to any variant of @Transactional
.
Issue 2
The runtime
scope has been removed from Gradle, so runtime("org.springframework:spring-jdbc")
becomes runtimeOnly("org.springframework:spring-jdbc")
.
Changing runtimeOnly("org.springframework:spring-jdbc")
to implementation("org.springframework:spring-jdbc")
places org.springframework.transaction.annotation.Transactional
onto my compile-time classpath, but I can't get the transaction interceptor to trigger.
Issue 3
The @Transactional
link in the docs redirects to https://docs.micronaut.io/latest/api/io/micronaut/spring/tx/annotation/Transactional.html, which doesn't exist.
Issue 4
Not sure if limited to this page, but clicking the Improve this doc
buttons yield a JS error, as the button link contains an unescaped newline:
Thanks!
Steps To Reproduce
- Launch the server
- Hit
GET http://localhost:8080/test
- Receive "Roll back" error (expected)
- Hit
GET http://localhost:8080/test
- Receive "table already exists" error, instead of the expected "roll back" error
If transactions were working, the table creation would be rolled back each time.
I've also debugged into io.micronaut.spring.tx.annotation.TransactionInterceptor#intercept
and can confirm that it's not being fired. The datasource is, however, wrapped in a TransactionAwareDataSourceProxy
.
Environment Information
- Operating System: Windows 10 Pro
- JDK Version: AdoptOpenJDK 11.0.7
Example Application
https://github.com/chrisparton1991/micronaut-transaction-test
Version
3.0.1 (also reproducible in 2.5.11)
It looks like the annotation processor isn't generating the $InterceptedDefinition
classes. The regular $HelloController$Definition
class etc. are being generated, so the annotation processor is running.
so Spring is no longer needed for transaction management so this documentation is indeed out of date.
If you do want Spring transaction management I believe you need to add micronaut-spring-annotation
to your annotationProcessor
classpath
Thanks, I'd be more than happy to use Miconaut's transaction management and remove Spring.
Is there a particular annotation/dependency required to use Micronaut transactions for a plain JDBC project? I can only see Spring-based docs in the hibernate-sql
guide.
Today I was able to get Spring transactions working in a v2->v3 project migration so it's no longer urgent for me.
I'm guessing this is pretty straightforward to answer and close this issue. I'm wondering the same thing.
so Spring is no longer needed for transaction management so this documentation is indeed out of date.
If you do want Spring transaction management I believe you need to add micronaut-spring-annotation to your annotationProcessor classpath
@graemerocher I keep seeing similar comments about what to do if you want to use micronaut-spring-annotation
but don't see a clear recommendation about how to set this up without it. Could you provide any info? Can jakarta.transaction-api
simply be added and @Transactional
used?
@matt-snider This PR seems to address this issue https://github.com/micronaut-projects/micronaut-sql/pull/557
@graemerocher But again, that shows how to set up transactions with Spring. Is it not possible without?
If you don't want to use Spring then just add javax.transaction.Transactional
. Currently we haven't moved the the jakarta namespace for this. A correctly configured project can be found in the guides https://guides.micronaut.io/latest/micronaut-data-jdbc-repository.html
See also https://micronaut-projects.github.io/micronaut-data/latest/guide/#transactions
@graemerocher Thanks so much. Both of those examples are for micronaut-data
though. I think OP and I are both talking about using just micronaut-sql
. But I assume your comment still holds true
If you don't want to use Spring then just add javax.transaction.Transactional.
@burtbeckwith could you add some docs on using Micronaut SQL with Micronaut TX without Micronaut Data to address this issue.
@graemerocher @burtbeckwith Very much appreciated :pray:
Some of these problems were reported in issue #555, in which case I sent an MR with the correction of part of the mentioned problems.
@burtbeckwith Do you have any guidance here? Haven't found a way to get @Transactional
to work with or without micronaut-data
. Is there a minimal project that shows this working?
Okay I've been struggling with this one for awhile and it turns out the TransactionalInterceptor
has been getting applied the whole time. The issue is that any methods not annotated with @Transactional
throw an exception and this lead me to believe something was very wrong with my setup.
Unexpected error occurred: No current transaction present. Consider declaring @Transactional on the surrounding method
io.micronaut.transaction.exceptions.NoTransactionException: No current transaction present. Consider declaring @Transactional on the surrounding method
at io.micronaut.transaction.jdbc.TransactionalConnectionInterceptor.intercept(TransactionalConnectionInterceptor.java:65)
// omitted
Caused by: io.micronaut.transaction.jdbc.exceptions.CannotGetJdbcConnectionException: No current JDBC Connection found. Consider wrapping this call in transactional boundaries.
at io.micronaut.transaction.jdbc.DataSourceUtils.doGetConnection(DataSourceUtils.java:135)
at io.micronaut.transaction.jdbc.DataSourceUtils.getConnection(DataSourceUtils.java:93)
So obviously I'm doing something wrong here because the Transactions Guide doesn't mention anything about all methods requiring the annotation (that wouldn't make sense?), In fact it even says:
You can simply declare a method as transactional with the javax.transaction.Transactional annotation.
You can see the TestController
in a repository I created to exemplify the issue
I was able to get transactions working without Spring by adding the dependencies
annotationProcessor("io.micronaut.data:micronaut-data-processor:3.2.2")
and implementation("io.micronaut.data:micronaut-data-tx")
. It turns out that the NoTransactionException
was caused by a bug which I reported in #1399
This issue was about outdated docs, so I hope I didn't derail the discussion too much. Still I wonder if the documentation should be improved here. There is a main section under JDBC about how to use Spring Transactions, but no such section about how to add Micronaut Transactions. Unless there is some reason micronaut-sql
+ micronaut-data-tx
are not recommend together, I think we should document this more clearly, otherwise most users will probably just set up Spring Transactions.
For me, personally, it was also confusing the first time, because we don't use micronaut-data
but need the micronaut-data-tx
to use with micronaut-sql
. Maybe the transactions module should be transfered to micronaut-sql
the same as is the reactive transactions module located in micronaut-r2dbc
?
I just ran into this again because I was trying to get JOOQ set up properly such that I have the JooqExceptionTranslator
and Transaction Manager from Spring but it doesn't seem to work. It seems like I get proper exception messages with compileOnly("org.springframework:spring-jdbc")
but then I don't have the transaction manager, and with runtimeOnly("org.springframework:spring-jdbc")
the transaction manager works but not the informative exceptions.
I think what I will try is to remove Spring Transaction management and switch to Micronaut and then implement my own JOOQ exception handler.
I think the documentation would be more clear with a subsection in JOOQ explaining how to set up Transaction management for each scenario (with Spring, without Spring) as well as how to get the JooqExceptionTranslator
working properly
This documentation is definitely missing. I'm currently trying to read through some tests that use transactions in this project; if the transactions work in the test, then the build.gradle must sufficiently add the right dependencies for transactions to work.
Looks like, at minimum, you need to add:
io.micronaut.data:micronaut-data-processor
io.micronaut.data:micronaut-data-tx
So, for Kotlin, assuming hikari:
dependencies {
kapt("io.micronaut.data:micronaut-data-processor")
implementation("io.micronaut.data:micronaut-data-tx")
implementation("io.micronaut.data:micronaut-data-tx-jdbc")
implementation("io.micronaut.sql:micronaut-jdbi")
runtimeOnly("io.micronaut.sql:micronaut-jdbc-hikari")
}
In short, you must include some Micronaut Data dependencies to get transaction management working in Micronaut SQL if you're not using Micronaut Spring.
Oh interesting! So Spring support was recently removed: https://github.com/micronaut-projects/micronaut-sql/pull/947 which makes documenting how to support transaction management even more important.
The documentation is still out of date. Regrettably, it looks like Micronaut 4 has made the docs even more out of date - my instructions are no longer accurate.
Can we have someone with a bit more Micronaut SQL expertise provide some direction on how to properly use transactions when not using Micronaut Data, assuming that's still supported?
Here's the new dependency that's now needed:
implementation("io.micronaut.data:micronaut-data-tx-jdbc")