quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.78k stars 2.68k forks source link

hibernate-reactive-panache gives error "No bean found for required type TransactionManager" #18565

Open AlexandreGuidin opened 3 years ago

AlexandreGuidin commented 3 years ago

Describe the bug

I've updated to Quarkus 2.0.1.Final and then updated hibernate panache to reactive version and it start logging this error after o make a request to whatever url

2021-07-09 09:45:38,132 WARN  [io.qua.arc.impl] (vert.x-eventloop-thread-6) 
================================================================================
CDI: programmatic lookup problem detected
-----------------------------------------
At least one bean matched the required type and qualifiers but was marked as unused and removed during build
Removed beans:
    - CLASS bean io.smallrye.context.jta.context.propagation.JtaContextProvider$LifecycleManager [types=[class io.smallrye.context.jta.context.propagation.JtaContextProvider$LifecycleManager], qualifiers=[@javax.enterprise.inject.Default(), @javax.enterprise.inject.Any()]]
Required type: class io.smallrye.context.jta.context.propagation.JtaContextProvider$LifecycleManager
Required qualifiers: [@javax.enterprise.inject.Default()]
Solutions:
    - Application developers can eliminate false positives via the @Unremovable annotation
    - Extensions can eliminate false positives via build items, e.g. using the UnremovableBeanBuildItem
    - See also https://quarkus.io/guides/cdi-reference#remove_unused_beans
================================================================================
2021-07-09 09:56:24,516 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (vert.x-eventloop-thread-6) HTTP Request to /error-error-whatever-url failed, error id: ef6fef6f-84ac-4448-a3f9-a580b2df94cb-2: javax.enterprise.inject.UnsatisfiedResolutionException: No bean found for required type [interface javax.transaction.TransactionManager] and qualifiers [[]]
    at io.quarkus.arc.impl.InstanceImpl.bean(InstanceImpl.java:175)
    at io.quarkus.arc.impl.InstanceImpl.getInternal(InstanceImpl.java:196)
    at io.quarkus.arc.impl.InstanceImpl.get(InstanceImpl.java:93)
    at io.smallrye.context.jta.context.propagation.JtaContextProvider.tm(JtaContextProvider.java:120)
    at io.smallrye.context.jta.context.propagation.JtaContextProvider.currentContext(JtaContextProvider.java:34)
    at io.smallrye.context.impl.ThreadContextProviderPlan.takeThreadContextSnapshots(ThreadContextProviderPlan.java:72)
    at io.smallrye.context.impl.SlowCapturedContextState.<init>(SlowCapturedContextState.java:25)
    at io.smallrye.context.SmallRyeThreadContext.captureContext(SmallRyeThreadContext.java:729)
    at io.smallrye.context.SmallRyeThreadContext.contextualSupplier(SmallRyeThreadContext.java:719)
    at io.smallrye.mutiny.context.BaseContextPropagationInterceptor.decorate(BaseContextPropagationInterceptor.java:353)
    at io.smallrye.mutiny.infrastructure.Infrastructure.decorate(Infrastructure.java:346)
    at io.smallrye.mutiny.groups.UniMemoize.until(UniMemoize.java:37)
    at io.smallrye.mutiny.groups.UniMemoize.indefinitely(UniMemoize.java:80)
    at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$2.handle(HttpSecurityRecorder.java:101)
    at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$2.handle(HttpSecurityRecorder.java:51)
    at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1127)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:151)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:133)
    at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$3.handle(VertxHttpHotReplacementSetup.java:88)
    at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$3.handle(VertxHttpHotReplacementSetup.java:77)
    at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:124)
    at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:54)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)

I've tried to delete almost everything of my code and configs to reach the cause of it, but the error keep logging

I tried to reproduce the same error with https://github.com/quarkusio/quarkus-quickstarts/tree/main/hibernate-reactive-panache-quickstart but even if i add all of my libraries, and change the active record pattern to repository pattern, add a liquibase and other stuff that i have in my project, i never got the same error here.

The only differente is that i use gradle and this quickstart use maven

I found same error without solution here https://stackoverflow.com/questions/67904868/quarkus-hibernate-no-bean-found-for-required-type-interface-javax-transaction-t. (it have some error at his configuration, but the error is the same of mine)

I'm out of ideas to fix it :(

To Reproduce

I could not share my project, and i was not able to reproduce this error on quickstart :(

But here are my configs

dependencies {
    implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")

    implementation 'io.quarkus:quarkus-resteasy-reactive-jackson'
    implementation 'io.quarkus:quarkus-hibernate-validator'

    implementation 'io.quarkus:quarkus-hibernate-reactive-panache'
    implementation 'io.quarkus:quarkus-reactive-pg-client'
    implementation 'com.vladmihalcea:hibernate-types-52:2.12.0'

    implementation 'io.quarkus:quarkus-jdbc-postgresql'
    implementation 'org.liquibase:liquibase-core:4.4.0'
    implementation 'com.google.cloud.sql:postgres-socket-factory:1.3.0'

    implementation 'io.quarkus:quarkus-security'
    implementation 'io.quarkus:quarkus-elytron-security-common'

    implementation 'com.auth0:java-jwt:3.16.0'
    implementation 'io.quarkus:quarkus-config-yaml'

    implementation 'org.graalvm.js:js:21.1.0'
    implementation 'org.graalvm.truffle:truffle-api:21.1.0'

    testImplementation 'io.quarkus:quarkus-junit5'
    testImplementation 'io.quarkus:quarkus-junit5-mockito'

    testImplementation 'io.rest-assured:rest-assured'
    testImplementation 'org.skyscreamer:jsonassert:1.5.0'
    testImplementation 'org.assertj:assertj-core:3.20.2'

}
  datasource:
    db-kind: postgresql
    reactive:
      url: ${DB_URL:vertx-reactive:postgresql://localhost:5432/xxxxxx?stringtype=unspecified}
    username: ${DB_USER:root}
    password: ${DB_PWD:root}
  hibernate-orm:
    database:
      generation: none
quarkus-bot[bot] commented 3 years ago

/cc @DavideD, @FroMage, @Sanne, @gavinking, @loicmathieu

AlexandreGuidin commented 3 years ago

I've created a new project from https://code.quarkus.io/?g=org.test&e=resteasy-reactive&e=resteasy-reactive-jackson&e=hibernate-reactive-panache&e=reactive-pg-client and copy Fruit and FruitResource from quickstart

image

Weird that with Maven it works, but Gradle it not, it throws that exception Already tried to clear gradle cache files, but no success

oberstrike commented 3 years ago

I have the same error. I additionally used Kotlin as programming language.

re-thc commented 3 years ago

Try adding quarkus-narayana-jta -- hibernate reactive depends on hibernate orm which depends on agroal / jta for some reason (not used in reactive?)

AlexandreGuidin commented 3 years ago

quarkus-narayana-jta

It worked. Don't know if i should add it, but it work for now.

FroMage commented 3 years ago

This is a very weird issue. It appears it was introduced by https://github.com/smallrye/smallrye-context-propagation/commit/eb454a70ca03b1aa6ddc8fa8a862db954d68a527 which introduced LifecycleManager in https://github.com/smallrye/smallrye-context-propagation/commit/eb454a70ca03b1aa6ddc8fa8a862db954d68a527#diff-6719340760b3e74dbd9230d39c1f683af6390f27307ee70d4660b917031f2f90R165 but we forgot to mark the bean as unremovable if smallrye-context-propagation-jta is present.

FroMage commented 3 years ago

Actually not true, since extensions/narayana-jta/deployment/src/main/java/io/quarkus/narayana/jta/deployment/NarayanaJtaProcessor.java marks it:

    @BuildStep
    UnremovableBeanBuildItem unremovableBean() {
        // LifecycleManager comes from smallrye-context-propagation-jta and is only used via programmatic lookup in JtaContextProvider
        return UnremovableBeanBuildItem.beanClassNames(JtaContextProvider.LifecycleManager.class.getName());
    }
FroMage commented 3 years ago

Ah, got it, it's normally imported by quarkus-hibernate-orm but is explicitely excluded by quarkus-hibernate-reactive:

        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-hibernate-orm</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.quarkus</groupId>
                    <artifactId>quarkus-agroal</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.quarkus</groupId>
                    <artifactId>quarkus-narayana-jta</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
FroMage commented 3 years ago

I guess I can tweak smallrye-context-propagation-jta to consider that if LifecycleManager is not available, then JTA must have been disabled. It's kinda weird, but it'd work. Or I can make quarkus-hibernate-reactive mark LifecycleManager as unremovable. That would also work, and perhaps be less weird, since it acknowledges that our import has an exclusion that has some side-effect. JTA would still not be propagated since TransactionManager would be an empty proxy. WDYT @stuartwdouglas ?

AlexandreGuidin commented 3 years ago

@FroMage

Other weird thing, you see that maven projects it works, but gradle it not ? at least until version 2.0.1.Final

stuartwdouglas commented 3 years ago

I think not propagating JTA is fine for HR.

JTA TX commit is a blocking operation, so we really don't want JTA for a 100% reactive approach anyway.

FroMage commented 3 years ago

I added a preliminary fix in SR-CP at https://github.com/smallrye/smallrye-context-propagation/pull/299 because I actually get an exception myself, before I get this warning, so it's more severe. Then I'll fix the warning too in Quarkus in https://github.com/quarkusio/quarkus/pull/18893