diff --git a/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java b/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java index f91a2072d1b..0441d9c89c0 100644 --- a/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java +++ b/quarkus/deployment/src/main/java/org/keycloak/quarkus/deployment/KeycloakProcessor.java @@ -53,6 +53,8 @@ import io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem; import io.quarkus.vertx.http.deployment.RouteBuildItem; import jakarta.persistence.Entity; import jakarta.persistence.PersistenceUnitTransactionType; +import org.eclipse.microprofile.config.spi.ConfigSource; +import org.hibernate.cfg.JdbcSettings; import org.eclipse.microprofile.health.Readiness; import org.hibernate.cfg.AvailableSettings; import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor; @@ -154,6 +156,7 @@ import java.util.Optional; import java.util.Properties; import java.util.ServiceLoader; import java.util.Set; +import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.jar.JarEntry; @@ -366,6 +369,47 @@ class KeycloakProcessor { recorder.setDefaultUserProfileConfiguration(configuration.getDefaultConfig()); } + /** + * Get datasource name obtained from the persistence.xml file based on this order: + *
Configures the persistence unit for Quarkus.
*
@@ -398,10 +442,11 @@ class KeycloakProcessor {
runtimeConfigured.produce(new HibernateOrmIntegrationRuntimeConfiguredBuildItem("keycloak", defaultUnitDescriptor.getName())
.setInitListener(recorder.createDefaultUnitListener()));
} else {
- Properties properties = descriptor.getProperties();
+ String datasourceName = getDatasourceNameFromPersistenceXml(descriptor);
+ configurePersistenceUnitProperties(datasourceName, descriptor);
// register a listener for customizing the unit configuration at runtime
runtimeConfigured.produce(new HibernateOrmIntegrationRuntimeConfiguredBuildItem("keycloak", descriptor.getName())
- .setInitListener(recorder.createUserDefinedUnitListener(properties.getProperty(AvailableSettings.DATASOURCE))));
+ .setInitListener(recorder.createUserDefinedUnitListener(datasourceName)));
userManagedEntities.addAll(descriptor.getManagedClassNames());
}
}
@@ -427,6 +472,25 @@ class KeycloakProcessor {
producer.produce(new PersistenceXmlDescriptorBuildItem(descriptor));
}
+ static void configurePersistenceUnitProperties(String datasourceName, ParsedPersistenceXmlDescriptor descriptor) {
+ Properties unitProperties = descriptor.getProperties();
+ var isResourceLocalSpecified = PersistenceUnitTransactionType.RESOURCE_LOCAL.equals(descriptor.getPersistenceUnitTransactionType()) ||
+ Optional.ofNullable(unitProperties.getProperty(AvailableSettings.JAKARTA_TRANSACTION_TYPE))
+ .map(f -> f.equalsIgnoreCase(PersistenceUnitTransactionType.RESOURCE_LOCAL.name()))
+ .orElse(false);
+ if (isResourceLocalSpecified) {
+ throw new IllegalArgumentException("You need to use '%s' transaction type in your persistence.xml file."
+ .formatted(PersistenceUnitTransactionType.JTA.name()));
+ }
+
+ unitProperties.setProperty(AvailableSettings.JAKARTA_TRANSACTION_TYPE, PersistenceUnitTransactionType.JTA.name());
+ descriptor.setTransactionType(PersistenceUnitTransactionType.JTA);
+
+ // set datasource name
+ unitProperties.setProperty(JdbcSettings.JAKARTA_JTA_DATASOURCE,datasourceName);
+ unitProperties.setProperty(AvailableSettings.DATASOURCE, datasourceName); // for backward compatibility
+ }
+
private void configureDefaultPersistenceUnitProperties(ParsedPersistenceXmlDescriptor descriptor, HibernateOrmConfig config,
JdbcDataSourceBuildItem defaultDataSource) {
if (defaultDataSource == null || !defaultDataSource.isDefault()) {
@@ -566,7 +630,7 @@ class KeycloakProcessor {
}
/**
- * Register the custom {@link org.eclipse.microprofile.config.spi.ConfigSource} implementations.
+ * Register the custom {@link ConfigSource} implementations.
*
* @param configSources
*/
diff --git a/quarkus/deployment/src/test/java/org/keycloak/quarkus/deployment/PersistenceXmlDatasourcesTest.java b/quarkus/deployment/src/test/java/org/keycloak/quarkus/deployment/PersistenceXmlDatasourcesTest.java
new file mode 100644
index 00000000000..86a812ef142
--- /dev/null
+++ b/quarkus/deployment/src/test/java/org/keycloak/quarkus/deployment/PersistenceXmlDatasourcesTest.java
@@ -0,0 +1,200 @@
+package org.keycloak.quarkus.deployment;
+
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.cfg.JdbcSettings;
+import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
+import org.hibernate.jpa.boot.spi.PersistenceXmlParser;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.function.Consumer;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.keycloak.quarkus.deployment.KeycloakProcessor.configurePersistenceUnitProperties;
+import static org.keycloak.quarkus.deployment.KeycloakProcessor.getDatasourceNameFromPersistenceXml;
+import static org.wildfly.common.Assert.assertNotNull;
+
+public class PersistenceXmlDatasourcesTest {
+ private static final String PERSISTENCE_XML_BODY = """
+ > asserts) throws IOException {
+ String finalPersistenceXmlFileContent = PERSISTENCE_XML_BODY.formatted(content);
+ Path persistenceXmlFile = null;
+ try {
+ persistenceXmlFile = Files.createTempFile("persistence", ".xml");
+ Files.writeString(persistenceXmlFile, finalPersistenceXmlFileContent);
+ asserts.accept(parser.parse(List.of(persistenceXmlFile.toUri().toURL())).values().stream().map(f -> (ParsedPersistenceXmlDescriptor) f).toList());
+ } finally {
+ if (persistenceXmlFile != null) {
+ Files.deleteIfExists(persistenceXmlFile);
+ }
+ }
+ }
+}
diff --git a/quarkus/tests/integration/src/test-providers/resources/com/acme/provider/legacy/jpa/entity/persistence.xml b/quarkus/tests/integration/src/test-providers/resources/com/acme/provider/legacy/jpa/entity/persistence.xml
index d4ad48e88cb..418210967cd 100644
--- a/quarkus/tests/integration/src/test-providers/resources/com/acme/provider/legacy/jpa/entity/persistence.xml
+++ b/quarkus/tests/integration/src/test-providers/resources/com/acme/provider/legacy/jpa/entity/persistence.xml
@@ -25,8 +25,7 @@