micronaut-guides
micronaut-guides copied to clipboard
transaction error when running tests and when creating genre in tutorial "ACCESS A DATABASE WITH JPA AND HIBERNATE"
Task List
- [x] Steps to reproduce provided
- [x] Stacktrace (if present) provided
- [x] Example that reproduces the problem uploaded to Github
- [x] Full description of the issue provided (see below)
Steps to Reproduce
- Begin tutorial at https://guides.micronaut.io/latest/micronaut-jpa-hibernate-gradle-java.html using VS Code. Skip the step to enable annotation processing because not using IntelliJ.
- For each step in the tutorial before the step "Testing the Application", run each command, copy configuration into
application.yml
, and create the Java files in the appropriate packages, copy and pasting the Java code into the Java files. - At the step "Testing the Application", run the command "./gradlew test" as the tutorial instructs. Observe the error:
...
GenreControllerTest > testGenreCrudOperations() FAILED
io.micronaut.http.client.exceptions.HttpClientResponseException at DefaultHttpClient.java:2146
...
- Run the command
./gradlew run
to start the application. Observe the application start successfully:
...
17:59:10.500 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 812ms. Server Running: http://localhost:8080
...
- Run the command
curl -s -XPOST localhost:8080/genres -H 'Content-Type: application/json' -d '{"name":"abc"}'
to attempt to create a new genre in the in-memory database using the code from the tutorial. Observe the error in the response:
{"message":"Internal Server Error: Could not obtain transaction-synchronized Session for current thread","_links":{"self":{"href":"/genres","templated":false}}}
and the error in the running program:
18:00:27.484 [io-executor-thread-1] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: Could not obtain transaction-synchronized Session for current thread
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at io.micronaut.transaction.hibernate5.MicronautSessionContext.currentSession(MicronautSessionContext.java:100)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:479)
at io.micronaut.configuration.hibernate.jpa.TransactionalSessionInterceptor.intercept(TransactionalSessionInterceptor.java:56)
at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:96)
at io.micronaut.configuration.hibernate.jpa.TransactionalSession$Intercepted.persist(Unknown Source)
at example.micronaut.GenreRepositoryImpl.save(GenreRepositoryImpl.java:41)
at example.micronaut.$GenreRepositoryImplDefinition$Intercepted.$$access$$save(Unknown Source)
at example.micronaut.$GenreRepositoryImplDefinition$$exec2.invokeInternal(Unknown Source)
at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:151)
at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:87)
at io.micronaut.validation.ValidatingInterceptor.intercept(ValidatingInterceptor.java:137)
at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:96)
at example.micronaut.$GenreRepositoryImplDefinition$Intercepted.save(Unknown Source)
at example.micronaut.GenreController.save(GenreController.java:54)
at example.micronaut.$GenreControllerDefinition$Intercepted.$$access$$save(Unknown Source)
at example.micronaut.$GenreControllerDefinition$$exec4.invokeInternal(Unknown Source)
at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:151)
at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:87)
at io.micronaut.validation.ValidatingInterceptor.intercept(ValidatingInterceptor.java:137)
at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:96)
at example.micronaut.$GenreControllerDefinition$Intercepted.save(Unknown Source)
at example.micronaut.$GenreControllerDefinition$$exec4.invokeInternal(Unknown Source)
at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:151)
at io.micronaut.context.DefaultBeanContext$4.invoke(DefaultBeanContext.java:482)
at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:303)
at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:121)
at io.micronaut.http.server.netty.RoutingInBoundHandler.emitRouteResponse(RoutingInBoundHandler.java:1502)
at io.micronaut.http.server.netty.RoutingInBoundHandler.access$2100(RoutingInBoundHandler.java:151)
at io.micronaut.http.server.netty.RoutingInBoundHandler$6$1.request(RoutingInBoundHandler.java:1469)
at io.reactivex.internal.subscriptions.SubscriptionHelper.deferredSetOnce(SubscriptionHelper.java:202)
at io.reactivex.internal.operators.single.SingleFlatMapPublisher$SingleFlatMapPublisherObserver.onSubscribe(SingleFlatMapPublisher.java:107)
at io.micronaut.http.server.netty.RoutingInBoundHandler$6.doSubscribe(RoutingInBoundHandler.java:1457)
at io.micronaut.http.server.netty.RoutingInBoundHandler$6.lambda$subscribe$0(RoutingInBoundHandler.java:1451)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:831)
Expected Behaviour
Expect no error in the response and no error in the logs of the running application. Expect no need to enable IDE specific settings because expecting Gradle to complete any build steps needed, including processing annotations.
Actual Behaviour
Errors encountered when trying to save genre. See above for details.
Environment Information
- Operating System:
> lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.2 LTS
Release: 20.04
Codename: focal
- Micronaut Version:
> mn --version
Micronaut Version: 2.5.8
- JDK Version:
> java --version
openjdk 16.0.1 2021-04-20
OpenJDK Runtime Environment (build 16.0.1+9-Ubuntu-120.04)
OpenJDK 64-Bit Server VM (build 16.0.1+9-Ubuntu-120.04, mixed mode, sharing)
Example Application
https://github.com/mattwelke/micronaut-bug-report-jpa-hibernate
Reviewing the tutorial, I decided to test whether or not the tutorial was built with IntelliJ in mind, such that one could not use VS Code because Gradle only does a subset of what is needed to build the application. I downloaded the complete solution from the tutorial, unzipped it, and without opening it in any IDE, ran ./gradlew test
in it. It worked fine.
At this point, I concluded that Gradle is able to build the application properly without the help of any IDE. So I suspected I may have missed something from the tutorial. I thought the issue might be related to annotation processing, so I looked at the complete example's build.gradle
file and noticed that it has the following for dependencies:
dependencies {
annotationProcessor("io.micronaut.data:micronaut-data-processor")
implementation("io.micronaut:micronaut-http-client")
implementation("io.micronaut:micronaut-runtime")
implementation("io.micronaut.data:micronaut-data-hibernate-jpa")
implementation("io.micronaut.sql:micronaut-hibernate-jpa")
implementation("io.micronaut.sql:micronaut-jdbc-hikari")
runtimeOnly("ch.qos.logback:logback-classic")
runtimeOnly("com.h2database:h2")
compileOnly("org.graalvm.nativeimage:svm")
implementation("io.micronaut:micronaut-validation")
}
I didn't recognize the line annotationProcessor("io.micronaut.data:micronaut-data-processor")
.
I checked my build.gradle
file from following the tutorial and found that I didn't have it. When I added it and ran ./gradlew test
again, it still didn't work. I noticed then that I had the line annotationProcessor("io.micronaut.data:micronaut-data-hibernate-jpa")
in my build.gradle
file, but the complete example did not. I removed it and ran the tests again. It still failed.
When comparing the build.gradle
files more, I found that I was able to get it to work by replacing the line implementation("io.micronaut.sql:micronaut-hibernate-jpa")
in my file with implementation("io.micronaut.data:micronaut-data-hibernate-jpa")
(which I saw in the completed example). I'm completely new to working with relational databases with Java, so I don't know why this particular change fixed the issue. But from what I experienced here, it looks like the tutorial was written in a way that expects certain things to generated in the build.gradle
file, and since it was written, that has changed. The completed example appears to have been kept up to date, but not the steps in the tutorial.