micronaut-projects / micronaut-sql

Projects to support SQL Database access in Micronaut
Apache License 2.0
72 stars 42 forks source link

Outdated documentation for JDBC Transaction management #558

Open chrisparton1991 opened 2 years ago

chrisparton1991 commented 2 years ago

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

Example Application

https://github.com/chrisparton1991/micronaut-transaction-test

Version

3.0.1 (also reproducible in 2.5.11)

chrisparton1991 commented 2 years ago

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.

graemerocher commented 2 years ago

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

chrisparton1991 commented 2 years ago

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.

matt-snider commented 2 years ago

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?

graemerocher commented 2 years ago

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

matt-snider commented 2 years ago

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

graemerocher commented 2 years ago

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 commented 2 years ago

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

matt-snider commented 2 years ago

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

graemerocher commented 2 years ago

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

matt-snider commented 2 years ago

@graemerocher @burtbeckwith Very much appreciated :pray:

viniciusxyz commented 2 years ago

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.

matt-snider commented 2 years ago

@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 commented 2 years ago

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 commented 2 years ago

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.

morki commented 2 years ago

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?

matt-snider commented 1 year ago

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

MT-Jacobs commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 9 months ago

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 commented 9 months ago

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

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