javadatasourcequarkusjta

Quarkus - programmatically retrieve named JTA datasource


Hi everyone I'm migrating from Wildfly to Quarkus, but unable to understand how to programmatically retrieve a named datasource. Below the code used until now in Wildfly to retrieve datasourceName programmatically (datasource datasourceName already defined in application.properties along with many others)

Properties p = new Properties();
p.put(AvailableSettings.DATASOURCE, datasourceName);
p.put(AvailableSettings.JTA_PLATFORM, JBossAppServerJtaPlatform.class.getName());
p.put("current_session_context_class", "jta");
p.put(AvailableSettings.SHOW_SQL, false);
p.put(AvailableSettings.FORMAT_SQL, false);
// Adding "hibernate.classLoaders" property is critical for this to work with keycloak!!!
p.put(AvailableSettings.CLASSLOADERS, Collections.singletonList(getClass().getClassLoader()));
entityManagerFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, p);

conf/quarkus.properties

quarkus.datasource.user-store.db-kind=mysql

quarkus.datasource.DATASOURCEA.db-kind=mysql
quarkus.datasource.DATASOURCEA.username=USER
quarkus.datasource.DATASOURCEA.password=PASSWORD
quarkus.datasource.DATASOURCEA.jdbc.url=jdbc:mysql://HOSTNAME/DATABASE

When running such code in Quarkus, exception is thrown

The FastbootHibernateProvider PersistenceProvider can not support runtime provided properties. Make sure you set all properties you need in the configuration resources before building the application.

given by this FastBootHibernatePersistenceProvider.java line

@SuppressWarnings("rawtypes")
private void verifyProperties(Map properties) {
    if (properties != null && properties.size() != 0) {
        throw new PersistenceException(
                "The FastbootHibernateProvider PersistenceProvider can not support runtime provided properties. "
                        + "Make sure you set all properties you need in the configuration resources before building the application.");
    }
}

Meaning, no property is allowed.

Tried with

Arc.container().instance(EntityManagerFactory.class, new PersistenceUnit.PersistenceUnitLiteral(datasourceName))

but throwing

WARN  [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator] (JPA Startup Thread: user-storage-jpa) HHH000342: Could not obtain connection to query metadata: java.lang.UnsupportedOperationException: The application must supply JDBC connections
at org.hibernate.engine.jdbc.connections.internal.UserSuppliedConnectionProviderImpl.getConnection(UserSuppliedConnectionProviderImpl.java:44)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:181)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68)

Any hint on this? Really struggling to find any useful reference to accomplish this. Can find only injection-based datasources.

thanks a lot, nicola


Solution

  • Have you seen the following? It is based on an example from one of the Keycloak Developers

    MyUserStorageProvider(KeycloakSession session, ComponentModel model) {
        this.session = session;
        this.model = model;
        em = session.getProvider(JpaConnectionProvider.class, "user-store").getEntityManager();
    }
    

    https://github.com/pedroigor/keycloak-quickstarts/blob/issue-10579/user-storage-jpa/src/main/java/org/keycloak/quickstart/storage/user/MyUserStorageProvider.java#L73