Closed bboyz269 closed 2 years ago
/cc @FroMage, @Sanne, @evanchooly, @gsmet, @loicmathieu, @yrodiere
Thanks for the report. Looks like a very weird issue, any chance you could share a small reproducer?
Thanks for the report. Looks like a very weird issue, any chance you could share a small reproducer?
@gsmet
Issue is reproducible with bare configuration. Please check this out.
https://github.com/bboyz269/hibernate-orm-panache-kotlin-multi-persistence-unit
@evanchooly could you have a look to see if it's a Kotlin-specific issue? We have tests for multiple persistence units support for Java I think so maybe it's a corner case but it might as well be Kotlin-related.
Thanks.
I think so maybe it's a corner case but it might as well be Kotlin-related.
FYI, switching to io.quarkus:quarkus-hibernate-orm-panache
and repository pattern works.
Persistence unit / entity manager could be resolved properly.
@Entity
@Table
class Admin(
@Id
@GeneratedValue
var id: Long = -1,
var name: String = ""
)
@Singleton
class AdminRepository : PanacheRepository<Admin>
after poking around the kotlin bits for a while i converted the project to use java. I get the same error after doing that as I did with kotlin (as shown above). So there's something off here for sure but i'm not 100% it's kotlin related. Perhaps one of the hibernate devs can take a look. @Sanne @FroMage?
I can look, can you share your Java reproducer please?
Thanks
I'm likely missing something obvious to someone more familiar with hibernate's innards but I ran out of places to poke around.
After quite a lot of hair pulling due to config and trying to follow the multi-tenant docs at https://quarkus.io/guides/hibernate-orm#multitenancy I had to:
TenantResolver
implementations for each tenant (no idea why one would not be enough)And then I tried it, and it works. I do get the following exceptions on startup, though, but I think that's another issue:
2021-07-20 16:39:14,548 WARN [org.hib.eng.jdb.env.int.JdbcEnvironmentInitiator] (JPA Startup Thread: cust) HHH000342: Could not obtain connection to query metadata: javax.enterprise.context.ContextNotActiveException
at io.quarkus.arc.impl.ClientProxies.getDelegate(ClientProxies.java:40)
at ac.me.entity.CustTenantResolver_ClientProxy.arc$delegate(CustTenantResolver_ClientProxy.zig:42)
at ac.me.entity.CustTenantResolver_ClientProxy.getDefaultTenantId(CustTenantResolver_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)
2021-07-20 16:39:14,548 WARN [org.hib.eng.jdb.env.int.JdbcEnvironmentInitiator] (JPA Startup Thread: admin) HHH000342: Could not obtain connection to query metadata: javax.enterprise.context.ContextNotActiveException
at io.quarkus.arc.impl.ClientProxies.getDelegate(ClientProxies.java:40)
at ac.me.entity.AdminTenantResolver_ClientProxy.arc$delegate(AdminTenantResolver_ClientProxy.zig:42)
at ac.me.entity.AdminTenantResolver_ClientProxy.getDefaultTenantId(AdminTenantResolver_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)
I can't quite understand why you had one data source as multitenant: https://github.com/bboyz269/hibernate-orm-panache-kotlin-multi-persistence-unit/blob/main/src/main/resources/application.yml#L21 Is it by mistake or on purpose?
My working project is at https://github.com/FroMage/quarkus-java-multi-pu
@FroMage
I can't quite understand why you had one data source as multitenant
It's intended. To say briefly, in order to resolve the tenant (which db schema to use for which tenant), my app needs to access another "admin" database, which manage all the tenant information.
Are you suggesting that adding "TenantResolver" for each persistence unit would solve the problem?
I suppose so, at least I had an error when I tried your config.
I suppose so, at least I had an error when I tried your config.
@FroMage I tried and got the same result (error due to AbstractJpaOperations#entityToPersistenceUnit being empty). I seems that private static volatile Map<String, String> entityToPersistenceUnit
is somehow messed up in kotlin.
I did some more digging on AbstractJpaOperations#entityToPersistenceUnit
and find the difference between "hibernate-orm-kotlin" and "hibernate-orm" is that:
One is build time work (entityToPersistenceUnit
is updated in build thread)
The other is runtime work (entityToPersistenceUnit
is updated in quarkus main thread)
I don't have any knowledge of Quarkus's extension framework ("Favor build time work over runtime work") but it seems that the former does not register entityToPersistenceUnit
mapping properly at runetime, causing problems with named persistence unit setup.
Do you think this worth investigating @evanchooly @FroMage ? I updated my repo with as reproducible (1 default datasource, 1 named persistence unit, fixed devservices)
@evanchooly could you look at this please?
Definitely.
There is a report of the same issue here: #20882 and I chased it down to the same causes, the entity to PU map is empty inside the Kotlin extension. @evanchooly @FroMage did you make any progress on it ?
Both Hibernate and Kotlin does it inside a STATIC_INIT
build step so I don't understand why it works in one but not in the other.
Pretty sure this was fixed in a later release
I just tested that this issue still exists in .2.4.0.Final".
There seems to be open PR that address this. Hope it get merged and released soon.
Describe the bug
I have 2 persistence units "admin" and "customer" associate with "c.s.c.e.admin" and "c.s.c.e.customer" packages.
Expected behavior
c.s.c.e.admin.Entity should work properly as before (1.13.6.Final).
Actual behavior
c.s.c.e.admin.Entity failed due to not able to resolve the associated persistence unit.
Masked stacktrace
Configuration
Screenshots
Direct cause would be
AbstractJpaOperations.entityToPersistenceUnit
lost it value (reverted after being set) to default emptyentityToPersistenceUnit map is being set (12 entries)
entityToPersistenceUnit is empty while being used
Reproduce steps
https://github.com/bboyz269/hibernate-orm-panache-kotlin-multi-persistence-unit