From 7933f0489d4fcd7ac5c66ec80450c771cb330814 Mon Sep 17 00:00:00 2001 From: Alexander Schwartz Date: Fri, 27 Jan 2023 10:23:08 +0100 Subject: [PATCH] Align startup of Quarkus with the regular startup to ensure boostrap locks are created. Also fixing an issue where DBLockGlobalLockProviderFactory held on to an old session, which lead to a closed DB connection on Quarkus. Closes #16642 --- .../liquibase/lock/LiquibaseDBLockProvider.java | 8 ++++---- .../models/dblock/DBLockGlobalLockProvider.java | 7 +++++-- .../dblock/DBLockGlobalLockProviderFactory.java | 8 ++------ .../jaxrs/QuarkusKeycloakApplication.java | 15 ++++----------- .../services/resources/KeycloakApplication.java | 4 ++-- 5 files changed, 17 insertions(+), 25 deletions(-) diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/lock/LiquibaseDBLockProvider.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/lock/LiquibaseDBLockProvider.java index 77ec842c43..d20bbceacc 100644 --- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/lock/LiquibaseDBLockProvider.java +++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/lock/LiquibaseDBLockProvider.java @@ -40,7 +40,7 @@ public class LiquibaseDBLockProvider implements DBLockProvider { private static final Logger logger = Logger.getLogger(LiquibaseDBLockProvider.class); // 10 should be sufficient - private int DEFAULT_MAX_ATTEMPTS = 10; + private final int DEFAULT_MAX_ATTEMPTS = 10; private final LiquibaseDBLockProviderFactory factory; @@ -83,9 +83,6 @@ public class LiquibaseDBLockProvider implements DBLockProvider { // Assumed transaction was rolled-back and we want to start with new DB connection private void restart() { safeCloseConnection(); - this.dbConnection = null; - this.lockService = null; - initialized = false; lazyInit(); } @@ -187,6 +184,9 @@ public class LiquibaseDBLockProvider implements DBLockProvider { if (dbConnection != null) { try { dbConnection.close(); + dbConnection = null; + lockService = null; + initialized = false; } catch (SQLException e) { logger.warn("Failed to close connection", e); } diff --git a/model/legacy-private/src/main/java/org/keycloak/models/dblock/DBLockGlobalLockProvider.java b/model/legacy-private/src/main/java/org/keycloak/models/dblock/DBLockGlobalLockProvider.java index f3908a033b..476cc7dab6 100644 --- a/model/legacy-private/src/main/java/org/keycloak/models/dblock/DBLockGlobalLockProvider.java +++ b/model/legacy-private/src/main/java/org/keycloak/models/dblock/DBLockGlobalLockProvider.java @@ -21,7 +21,6 @@ import org.jboss.logging.Logger; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionTaskWithResult; import org.keycloak.models.locking.GlobalLockProvider; -import org.keycloak.models.utils.KeycloakModelUtils; import java.time.Duration; import java.util.Objects; @@ -69,8 +68,12 @@ public class DBLockGlobalLockProvider implements GlobalLockProvider { LOG.debug("DBLockGlobalLockProvider does not support setting timeToWaitForLock per lock."); } + if (dbLockProvider.getCurrentLock() != null) { + throw new IllegalStateException("this lock is not reentrant, already locked for " + dbLockProvider.getCurrentLock()); + } + + dbLockProvider.waitForLock(stringToNamespace(lockName)); try { - dbLockProvider.waitForLock(stringToNamespace(lockName)); return task.run(session); } finally { releaseLock(lockName); diff --git a/model/legacy-private/src/main/java/org/keycloak/models/dblock/DBLockGlobalLockProviderFactory.java b/model/legacy-private/src/main/java/org/keycloak/models/dblock/DBLockGlobalLockProviderFactory.java index f52bd4f748..d34c31bd2b 100644 --- a/model/legacy-private/src/main/java/org/keycloak/models/dblock/DBLockGlobalLockProviderFactory.java +++ b/model/legacy-private/src/main/java/org/keycloak/models/dblock/DBLockGlobalLockProviderFactory.java @@ -28,15 +28,11 @@ import org.keycloak.provider.EnvironmentDependentProviderFactory; public class DBLockGlobalLockProviderFactory implements GlobalLockProviderFactory, EnvironmentDependentProviderFactory { public static final String PROVIDER_ID = "dblock"; - private DBLockManager dbLockManager; @Override public GlobalLockProvider create(KeycloakSession session) { - if (dbLockManager == null) { - dbLockManager = new DBLockManager(session); - dbLockManager.checkForcedUnlock(); - } - + DBLockManager dbLockManager = new DBLockManager(session); + dbLockManager.checkForcedUnlock(); return new DBLockGlobalLockProvider(session, dbLockManager.getDBLock()); } diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/integration/jaxrs/QuarkusKeycloakApplication.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/integration/jaxrs/QuarkusKeycloakApplication.java index 1a94fc5e22..e746a59eb9 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/integration/jaxrs/QuarkusKeycloakApplication.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/integration/jaxrs/QuarkusKeycloakApplication.java @@ -21,8 +21,8 @@ import java.util.Set; import java.util.stream.Collectors; import javax.ws.rs.ApplicationPath; -import org.keycloak.exportimport.ExportImportManager; -import org.keycloak.models.utils.PostMigrationEvent; + +import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.quarkus.runtime.integration.QuarkusKeycloakSessionFactory; import org.keycloak.services.resources.KeycloakApplication; import org.keycloak.quarkus.runtime.services.resources.QuarkusWelcomeResource; @@ -36,17 +36,10 @@ public class QuarkusKeycloakApplication extends KeycloakApplication { } @Override - protected void startup() { + public KeycloakSessionFactory createSessionFactory() { QuarkusKeycloakSessionFactory instance = QuarkusKeycloakSessionFactory.getInstance(); - sessionFactory = instance; instance.init(); - ExportImportManager exportImportManager = bootstrap(); - - if (exportImportManager.isRunExport()) { - exportImportManager.runExport(); - } - - sessionFactory.publish(new PostMigrationEvent(sessionFactory)); + return instance; } @Override diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java index 4269e29744..0ca2b29c68 100644 --- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java +++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java @@ -82,7 +82,7 @@ public class KeycloakApplication extends Application { protected Set singletons = new HashSet<>(); protected Set> classes = new HashSet<>(); - protected static KeycloakSessionFactory sessionFactory; + private static KeycloakSessionFactory sessionFactory; public KeycloakApplication() { @@ -237,7 +237,7 @@ public class KeycloakApplication extends Application { } - public static KeycloakSessionFactory createSessionFactory() { + protected KeycloakSessionFactory createSessionFactory() { DefaultKeycloakSessionFactory factory = new DefaultKeycloakSessionFactory(); factory.init(); return factory;