micronaut-sql icon indicating copy to clipboard operation
micronaut-sql copied to clipboard

Outdated documentation for JDBC Transaction management

Open chrisparton1991 opened this issue 3 years ago • 22 comments

Expected Behavior

  1. Create a new project using https://launch.micronaut.io. Default settings, but with jdbc-hikari added: image

  2. 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.

image

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: image

Thanks!

Steps To Reproduce

  1. Launch the server
  2. Hit GET http://localhost:8080/test
  3. Receive "Roll back" error (expected)
  4. Hit GET http://localhost:8080/test
  5. 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)

chrisparton1991 avatar Sep 23 '21 22:09 chrisparton1991

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.

chrisparton1991 avatar Sep 27 '21 01:09 chrisparton1991

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 avatar Sep 27 '21 08:09 graemerocher

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.

chrisparton1991 avatar Sep 27 '21 09:09 chrisparton1991

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 avatar Feb 10 '22 20:02 matt-snider

@matt-snider This PR seems to address this issue https://github.com/micronaut-projects/micronaut-sql/pull/557

graemerocher avatar Feb 11 '22 09:02 graemerocher

@graemerocher But again, that shows how to set up transactions with Spring. Is it not possible without?

matt-snider avatar Feb 11 '22 09:02 matt-snider

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

graemerocher avatar Feb 11 '22 10:02 graemerocher

See also https://micronaut-projects.github.io/micronaut-data/latest/guide/#transactions

graemerocher avatar Feb 11 '22 10:02 graemerocher

@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.

matt-snider avatar Feb 11 '22 10:02 matt-snider

@burtbeckwith could you add some docs on using Micronaut SQL with Micronaut TX without Micronaut Data to address this issue.

graemerocher avatar Feb 11 '22 10:02 graemerocher

@graemerocher @burtbeckwith Very much appreciated :pray:

matt-snider avatar Feb 11 '22 10:02 matt-snider

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.

viniciusxyz avatar Mar 11 '22 12:03 viniciusxyz

@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?

matt-snider avatar Mar 17 '22 18:03 matt-snider

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

matt-snider avatar Mar 17 '22 19:03 matt-snider

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.

matt-snider avatar Mar 23 '22 08:03 matt-snider

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?

morki avatar Jul 01 '22 09:07 morki

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

matt-snider avatar Dec 13 '22 18:12 matt-snider

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.

MT-Jacobs avatar Jun 28 '23 13:06 MT-Jacobs

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.

MT-Jacobs avatar Jul 05 '23 16:07 MT-Jacobs

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.

MT-Jacobs avatar Jul 05 '23 16:07 MT-Jacobs

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?

MT-Jacobs avatar Dec 13 '23 19:12 MT-Jacobs

Here's the new dependency that's now needed:

implementation("io.micronaut.data:micronaut-data-tx-jdbc")

MT-Jacobs avatar Dec 18 '23 16:12 MT-Jacobs