Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hibernate Multitenant project with a @RequestScoped TenantResolver throws javax.enterprise.context.ContextNotActiveException #19467

Closed
ramirogm opened this issue Aug 18, 2021 · 13 comments · Fixed by #19618
Labels
area/hibernate-orm Hibernate ORM area/persistence OBSOLETE, DO NOT USE kind/bug Something isn't working
Milestone

Comments

@ramirogm
Copy link

ramirogm commented Aug 18, 2021

Describe the bug

I'm using the SCHEMA hibernate multitenant option, implementing a TenantResolver that is @RequestScoped so that I can use an @Injected JsonWebToken

At startup, the app logs a warning when trying to call the getDefaultTenantId method to get the connection metadata ( see below ). This happens in 2.1., and didn't happen in 1.1., so it seems a regression.

More severe is that if I use the hibernate migrations(*), the app won't start as it can't get the default tenant. The error stack is similar but it's triggered from the migration classes. See the attached multitenant-2.1.2-migrate.zip file

2021-08-17 23:16:05,767 ERROR [io.qua.run.Application] (Quarkus Main Thread) Failed to start application (with profile dev): javax.enterprise.context.ContextNotActiveException
	at io.quarkus.arc.impl.ClientProxies.getDelegate(ClientProxies.java:40)
	at io.portx.quarkus.multitenant.CableTenantResolver_ClientProxy.arc$delegate(CableTenantResolver_ClientProxy.zig:42)
	at io.portx.quarkus.multitenant.CableTenantResolver_ClientProxy.getDefaultTenantId(CableTenantResolver_ClientProxy.zig:128)
	at io.quarkus.hibernate.orm.runtime.tenant.HibernateMultiTenantConnectionProvider.getAnyConnectionProvider(HibernateMultiTenantConnectionProvider.java:37)
	at org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider.getAnyConnection(AbstractMultiTenantConnectionProvider.java:26)
	at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$MultiTenantConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:208)
	at org.hibernate.resource.transaction.backend.jta.internal.DdlTransactionIsolatorJtaImpl.<init>(DdlTransactionIsolatorJtaImpl.java:59)
	at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl.buildDdlTransactionIsolator(JtaTransactionCoordinatorBuilderImpl.java:46)
	at org.hibernate.tool.schema.internal.HibernateSchemaManagementTool.getDdlTransactionIsolator(HibernateSchemaManagementTool.java:189)
	at org.hibernate.tool.schema.internal.HibernateSchemaManagementTool.buildGenerationTargets(HibernateSchemaManagementTool.java:147)
	at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop(SchemaDropperImpl.java:110)
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:153)
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:81)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:327)
	at io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder.build(FastBootEntityManagerFactoryBuilder.java:71)
	at io.quarkus.hibernate.orm.runtime.FastBootHibernatePersistenceProvider.createEntityManagerFactory(FastBootHibernatePersistenceProvider.java:67)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:80)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
	at io.quarkus.hibernate.orm.runtime.JPAConfig$LazyPersistenceUnit.get(JPAConfig.java:149)
	at io.quarkus.hibernate.orm.runtime.JPAConfig$1.run(JPAConfig.java:58)
	at java.base/java.lang.Thread.run(Thread.java:829)

(*) I know that https://quarkus.io/guides/hibernate-orm#configuring-the-application doesn't recommend using the hibernate generation with a multitenant config, but it's useful for a dev or test setup where I run just one schema.

To avoid this warning/error, as a workaround I have to use an @ApplicationScoped TenantResolver and then get the JsonWebToken "manually" using:

    if ( Arc.container().requestContext().isActive() ) {
      jwt = CDI.current().select(JsonWebToken.class).get();
    } else {
      throw new RuntimeException("Could not extract tenant information from JWT because the RequestContext is not active");
    }

Here's the full stack trace:

2021-08-17 22:04:56,066 WARN  [org.hib.eng.jdb.env.int.JdbcEnvironmentInitiator] (JPA Startup Thread: <default>) HHH000342: Could not obtain connection to query metadata: javax.enterprise.context.ContextNotActiveException
	at io.quarkus.arc.impl.ClientProxies.getDelegate(ClientProxies.java:40)
	at io.portx.quarkus.multitenant.CableTenantResolver_ClientProxy.arc$delegate(CableTenantResolver_ClientProxy.zig:42)
	at io.portx.quarkus.multitenant.CableTenantResolver_ClientProxy.getDefaultTenantId(CableTenantResolver_ClientProxy.zig:128)
	at io.quarkus.hibernate.orm.runtime.tenant.HibernateMultiTenantConnectionProvider.getAnyConnectionProvider(HibernateMultiTenantConnectionProvider.java:37)
	at org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider.getAnyConnection(AbstractMultiTenantConnectionProvider.java:26)
	at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$MultiTenantConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:208)
	at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68)
	at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
	at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:101)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
	at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51)
	at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:107)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:246)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
	at org.hibernate.boot.internal.SessionFactoryOptionsBuilder.<init>(SessionFactoryOptionsBuilder.java:263)
	at io.quarkus.hibernate.orm.runtime.recording.PrevalidatedQuarkusMetadata.buildSessionFactoryOptionsBuilder(PrevalidatedQuarkusMetadata.java:69)
	at io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder.build(FastBootEntityManagerFactoryBuilder.java:69)
	at io.quarkus.hibernate.orm.runtime.FastBootHibernatePersistenceProvider.createEntityManagerFactory(FastBootHibernatePersistenceProvider.java:67)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:80)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
	at io.quarkus.hibernate.orm.runtime.JPAConfig$LazyPersistenceUnit.get(JPAConfig.java:149)
	at io.quarkus.hibernate.orm.runtime.JPAConfig$1.run(JPAConfig.java:58)
	at java.base/java.lang.Thread.run(Thread.java:829)

Expected behavior

No warnings, TenantResolver created and getDefaultTenantId called

Actual behavior

See stack trace above

How to Reproduce?

I'm adding a mvn project to reproduce the error. Run ./mvnw compile quarkus:dev
multitenant-2.1.2.zip

Compare with the 1.1.7 version which runs ok ( this needs a pg db running )
1.1.7.zip

Output of uname -a or ver

Darwin MBP-15-Ramiro.local 20.4.0 Darwin Kernel Version 20.4.0: Thu Apr 22 21:46:47 PDT 2021; root:xnu-7195.101.2~1/RELEASE_X86_64 x86_64

Output of java -version

openjdk version "11.0.11" 2021-04-20 OpenJDK Runtime Environment AdoptOpenJDK-11.0.11+9 (build 11.0.11+9) OpenJDK 64-Bit Server VM AdoptOpenJDK-11.0.11+9 (build 11.0.11+9, mixed mode)

GraalVM version (if different from Java)

not used

Quarkus version or git rev

2.1.2.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: /Users/ramiro/.m2/wrapper/dists/apache-maven-3.6.3-bin/1iopthnavndlasol9gbrbg6bf2/apache-maven-3.6.3 Java version: 11.0.11, vendor: AdoptOpenJDK, runtime: /Users/ramiro/.sdkman/candidates/java/11.0.11.hs-adpt Default locale: en_AR, platform encoding: UTF-8 OS name: "mac os x", version: "11.3", arch: "x86_64", family: "mac"

Additional information

No response

@ramirogm ramirogm added the kind/bug Something isn't working label Aug 18, 2021
@quarkus-bot
Copy link

quarkus-bot bot commented Aug 18, 2021

/cc @Sanne, @gsmet, @yrodiere

@quarkus-bot quarkus-bot bot added area/hibernate-orm Hibernate ORM area/persistence OBSOLETE, DO NOT USE labels Aug 18, 2021
@ramirogm
Copy link
Author

@stefanorg
Copy link

+1 same here

@stefanorg
Copy link

also i noticed that in v 2.1.x quarkus raise a warning but the application work.
In version 2.2.0.CR1 i get also a null pointer exception

2021-08-20 11:46:02,069 ERROR [io.quark.deplo.dev.IsolatedDevModeMain:236] (vert.x-worker-thread-0) [{}] Failed to start quarkus: java.lang.RuntimeException: java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.dev.appstate.ApplicationStateNotification.waitForApplicationStart(ApplicationStateNotification.java:51)
        at io.quarkus.runner.bootstrap.StartupActionImpl.runMainClass(StartupActionImpl.java:109)
        at io.quarkus.deployment.dev.IsolatedDevModeMain.restartApp(IsolatedDevModeMain.java:227)
        at io.quarkus.deployment.dev.IsolatedDevModeMain.restartCallback(IsolatedDevModeMain.java:208)
        at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:499)
        at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:399)
        at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$4.handle(VertxHttpHotReplacementSetup.java:150)
        at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$4.handle(VertxHttpHotReplacementSetup.java:138)
        at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:160)
        at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:96)
        at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$1(ContextImpl.java:158)
        at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:1330)
        at io.quarkus.runtime.Application.start(Application.java:101)
        at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:101)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:66)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:42)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:119)
        at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:98)
        ... 1 more
Caused by: java.lang.RuntimeException: java.lang.NullPointerException
        at io.quarkus.hibernate.orm.runtime.JPAConfig.startAll(JPAConfig.java:72)
        at io.quarkus.hibernate.orm.runtime.JPAConfig_Subclass.startAll$$superforward1(JPAConfig_Subclass.zig:296)
        at io.quarkus.hibernate.orm.runtime.JPAConfig_Subclass$$function$$6.apply(JPAConfig_Subclass$$function$$6.zig:24)
        at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
        at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
        at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:51)
        at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(InvocationInterceptor_Bean.zig:521)
        at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
        at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
        at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
        at io.quarkus.hibernate.orm.runtime.JPAConfig_Subclass.startAll(JPAConfig_Subclass.zig:794)
        at io.quarkus.hibernate.orm.runtime.HibernateOrmRecorder.startAllPersistenceUnits(HibernateOrmRecorder.java:96)
        at io.quarkus.deployment.steps.HibernateOrmProcessor$startPersistenceUnits1868654632.deploy_0(HibernateOrmProcessor$startPersistenceUnits1868654632.zig:74)
        at io.quarkus.deployment.steps.HibernateOrmProcessor$startPersistenceUnits1868654632.deploy(HibernateOrmProcessor$startPersistenceUnits1868654632.zig:40)
        at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:1193)
        ... 12 more
Caused by: java.lang.NullPointerException
        at io.quarkus.hibernate.orm.runtime.FastBootHibernatePersistenceProvider.injectRuntimeConfiguration(FastBootHibernatePersistenceProvider.java:376)
        at io.quarkus.hibernate.orm.runtime.FastBootHibernatePersistenceProvider.getEntityManagerFactoryBuilderOrNull(FastBootHibernatePersistenceProvider.java:183)
        at io.quarkus.hibernate.orm.runtime.FastBootHibernatePersistenceProvider.createEntityManagerFactory(FastBootHibernatePersistenceProvider.java:61)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:80)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
        at io.quarkus.hibernate.orm.runtime.JPAConfig$LazyPersistenceUnit.get(JPAConfig.java:149)
        at io.quarkus.hibernate.orm.runtime.JPAConfig$1.run(JPAConfig.java:58)
        ... 1 more

@gastaldi
Copy link
Contributor

@stefanorg how do I reproduce the error you mentioned in #19467 (comment)? Can you provide a sample app?

@gastaldi
Copy link
Contributor

@stefanorg I created #19593 and provided a potential fix, can you test and let me know if that works for you?

@stefanorg
Copy link

ok @gastaldi, thank you. I'll build the PR and let you know.

@stefanorg
Copy link

stefanorg commented Aug 24, 2021

@gastaldi i confirm that your PR fixes the NPE.
The ContextNotActive still persist, any hint?

2021-08-24 10:19:14,672 WARN  [org.hiber.engin.jdbc.env.inter.JdbcEnvironmentInitiator:133] (JPA Startup Thread: argodb) [{}] HHH000342: Could not obtain connection to query metadata: javax.enterprise.context.ContextNotActiveException
        at io.quarkus.arc.impl.ClientProxies.getDelegate(ClientProxies.java:40)
        at it.argosoft.remotelogin.orm.tenant.ArgoDbTenantResolver_ClientProxy.arc$delegate(ArgoDbTenantResolver_ClientProxy.zig:42)
        at it.argosoft.remotelogin.orm.tenant.ArgoDbTenantResolver_ClientProxy.getDefaultTenantId(ArgoDbTenantResolver_ClientProxy.zig:128)
        at io.quarkus.hibernate.orm.runtime.tenant.HibernateMultiTenantConnectionProvider.getAnyConnectionProvider(HibernateMultiTenantConnectionProvider.java:37)
        at org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider.getAnyConnection(AbstractMultiTenantConnectionProvider.java:26)
        at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$MultiTenantConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:208)
        at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68)
        at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
        at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:101)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
        at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51)
        at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:107)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:246)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
        at org.hibernate.boot.internal.SessionFactoryOptionsBuilder.<init>(SessionFactoryOptionsBuilder.java:263)
        at io.quarkus.hibernate.orm.runtime.recording.PrevalidatedQuarkusMetadata.buildSessionFactoryOptionsBuilder(PrevalidatedQuarkusMetadata.java:69)
        at io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder.build(FastBootEntityManagerFactoryBuilder.java:69)
        at io.quarkus.hibernate.orm.runtime.FastBootHibernatePersistenceProvider.createEntityManagerFactory(FastBootHibernatePersistenceProvider.java:67)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:80)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
        at io.quarkus.hibernate.orm.runtime.JPAConfig$LazyPersistenceUnit.get(JPAConfig.java:149)
        at io.quarkus.hibernate.orm.runtime.JPAConfig$1.run(JPAConfig.java:58)
        at java.base/java.lang.Thread.run(Thread.java:834)

@gastaldi
Copy link
Contributor

@stefanorg thanks for testing it! Can you share your it.argosoft.remotelogin.orm.tenant.ArgoDbTenantResolver code?

@gastaldi
Copy link
Contributor

@stefanorg no need to share it, I can reproduce this issue with the following TenantResolver:

@RequestScoped
public class MyTenantResolver implements TenantResolver {

    @Override
    public String getDefaultTenantId() {
        return "Tenant";
    }

    @Override
    public String resolveTenantId() {
        return "Abc";
    }
}

And this is my application.properties:

quarkus.hibernate-orm.database.generation=create
quarkus.hibernate-orm.multitenant=DATABASE

@stefanorg
Copy link

Sorry for late response, yes nothing fancy on my side, only request scoped resolver with custom tenant resolver logic that depends on static configuration.

@gastaldi
Copy link
Contributor

@stefanorg can you build #19618 and let me know if that works for you?

@stefanorg
Copy link

@gastaldi to me seems ok, no more warnings 👍

@quarkus-bot quarkus-bot bot added this to the 2.3 - main milestone Aug 24, 2021
@gsmet gsmet modified the milestones: 2.3 - main, 2.2.0.Final, 2.1.4.Final Aug 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/hibernate-orm Hibernate ORM area/persistence OBSOLETE, DO NOT USE kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants