keycloak-aplcache

Details

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 5874084..7c48499 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
@@ -48,32 +48,35 @@ public class LiquibaseDBLockProvider implements DBLockProvider {
 
     private CustomLockService lockService;
     private Connection dbConnection;
+    private boolean initialized = false;
 
     private int maxAttempts = DEFAULT_MAX_ATTEMPTS;
 
     public LiquibaseDBLockProvider(LiquibaseDBLockProviderFactory factory, KeycloakSession session) {
         this.factory = factory;
         this.session = session;
-        init();
     }
 
-    private void init() {
-        LiquibaseConnectionProvider liquibaseProvider = session.getProvider(LiquibaseConnectionProvider.class);
-        JpaConnectionProviderFactory jpaProviderFactory = (JpaConnectionProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(JpaConnectionProvider.class);
+    private void lazyInit() {
+        if (!initialized) {
+            LiquibaseConnectionProvider liquibaseProvider = session.getProvider(LiquibaseConnectionProvider.class);
+            JpaConnectionProviderFactory jpaProviderFactory = (JpaConnectionProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(JpaConnectionProvider.class);
 
-        this.dbConnection = jpaProviderFactory.getConnection();
-        String defaultSchema = jpaProviderFactory.getSchema();
+            this.dbConnection = jpaProviderFactory.getConnection();
+            String defaultSchema = jpaProviderFactory.getSchema();
 
-        try {
-            Liquibase liquibase = liquibaseProvider.getLiquibase(dbConnection, defaultSchema);
+            try {
+                Liquibase liquibase = liquibaseProvider.getLiquibase(dbConnection, defaultSchema);
 
-            this.lockService = new CustomLockService();
-            lockService.setChangeLogLockWaitTime(factory.getLockWaitTimeoutMillis());
-            lockService.setDatabase(liquibase.getDatabase());
-        } catch (LiquibaseException exception) {
-            safeRollbackConnection();
-            safeCloseConnection();
-            throw new IllegalStateException(exception);
+                this.lockService = new CustomLockService();
+                lockService.setChangeLogLockWaitTime(factory.getLockWaitTimeoutMillis());
+                lockService.setDatabase(liquibase.getDatabase());
+                initialized = true;
+            } catch (LiquibaseException exception) {
+                safeRollbackConnection();
+                safeCloseConnection();
+                throw new IllegalStateException(exception);
+            }
         }
     }
 
@@ -82,12 +85,15 @@ public class LiquibaseDBLockProvider implements DBLockProvider {
         safeCloseConnection();
         this.dbConnection = null;
         this.lockService = null;
-        init();
+        initialized = false;
+        lazyInit();
     }
 
 
     @Override
     public void waitForLock() {
+        lazyInit();
+
         while (maxAttempts > 0) {
             try {
                 lockService.waitForLock();
@@ -110,6 +116,8 @@ public class LiquibaseDBLockProvider implements DBLockProvider {
 
     @Override
     public void releaseLock() {
+        lazyInit();
+
         lockService.releaseLock();
         lockService.reset();
         factory.setHasLock(false);
@@ -128,6 +136,8 @@ public class LiquibaseDBLockProvider implements DBLockProvider {
 
     @Override
     public void destroyLockInfo() {
+        lazyInit();
+
         try {
             this.lockService.destroy();
             dbConnection.commit();
@@ -154,7 +164,7 @@ public class LiquibaseDBLockProvider implements DBLockProvider {
     }
 
     private void safeCloseConnection() {
-        // Close after creating EntityManagerFactory to prevent in-mem databases from closing
+        // Close to prevent in-mem databases from closing
         if (dbConnection != null) {
             try {
                 dbConnection.close();
diff --git a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml b/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml
index 2d0117e..6b9ab90 100644
--- a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml
+++ b/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml
@@ -32,4 +32,6 @@
     <include file="META-INF/jpa-changelog-1.9.0.xml"/>
     <include file="META-INF/db2-jpa-changelog-1.9.1.xml"/>
     <include file="META-INF/jpa-changelog-1.9.2.xml"/>
+
+    <include file="META-INF/jpa-changelog-authz-master.xml"/>
 </databaseChangeLog>
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 818d571..0385281 100644
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -27,6 +27,7 @@ import org.keycloak.migration.MigrationModelManager;
 import org.keycloak.models.*;
 import org.keycloak.models.dblock.DBLockProvider;
 import org.keycloak.models.dblock.DBLockManager;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.models.utils.PostMigrationEvent;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.representations.idm.RealmRepresentation;
@@ -91,53 +92,28 @@ public class KeycloakApplication extends Application {
 
         singletons.add(new ObjectMapperResolver(Boolean.parseBoolean(System.getProperty("keycloak.jsonPrettyPrint", "false"))));
 
-        ExportImportManager exportImportManager;
-
-        DBLockManager dbLockManager = new DBLockManager(sessionFactory.create());
-        dbLockManager.checkForcedUnlock();
-        DBLockProvider dbLock = dbLockManager.getDBLock();
-        dbLock.waitForLock();
-        try {
-            migrateModel();
-
-            KeycloakSession session = sessionFactory.create();
-            try {
-                session.getTransaction().begin();
+        ExportImportManager[] exportImportManager = new ExportImportManager[1];
 
-                ApplianceBootstrap applianceBootstrap = new ApplianceBootstrap(session);
-                exportImportManager = new ExportImportManager(session);
+        KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
 
-                boolean createMasterRealm = applianceBootstrap.isNewInstall();
-                if (exportImportManager.isRunImport() && exportImportManager.isImportMasterIncluded()) {
-                    createMasterRealm = false;
-                }
-
-                if (createMasterRealm) {
-                    applianceBootstrap.createMasterRealm(contextPath);
-                }
-                session.getTransaction().commit();
-            } catch (RuntimeException re) {
-                if (session.getTransaction().isActive()) {
-                    session.getTransaction().rollback();
+            @Override
+            public void run(KeycloakSession lockSession) {
+                DBLockManager dbLockManager = new DBLockManager(lockSession);
+                dbLockManager.checkForcedUnlock();
+                DBLockProvider dbLock = dbLockManager.getDBLock();
+                dbLock.waitForLock();
+                try {
+                    exportImportManager[0] = migrateAndBootstrap();
+                } finally {
+                    dbLock.releaseLock();
                 }
-                throw re;
-            } finally {
-                session.close();
             }
 
-            if (exportImportManager.isRunImport()) {
-                exportImportManager.runImport();
-            } else {
-                importRealms();
-            }
+        });
 
-            importAddUser();
-        } finally {
-            dbLock.releaseLock();
-        }
 
-        if (exportImportManager.isRunExport()) {
-            exportImportManager.runExport();
+        if (exportImportManager[0].isRunExport()) {
+            exportImportManager[0].runExport();
         }
 
         boolean bootstrapAdminUser = false;
@@ -158,6 +134,49 @@ public class KeycloakApplication extends Application {
         setupScheduledTasks(sessionFactory);
     }
 
+
+    // Migrate model, bootstrap master realm, import realms and create admin user. This is done with acquired dbLock
+    protected ExportImportManager migrateAndBootstrap() {
+        ExportImportManager exportImportManager;
+        migrateModel();
+
+        KeycloakSession session = sessionFactory.create();
+        try {
+            session.getTransaction().begin();
+
+            ApplianceBootstrap applianceBootstrap = new ApplianceBootstrap(session);
+            exportImportManager = new ExportImportManager(session);
+
+            boolean createMasterRealm = applianceBootstrap.isNewInstall();
+            if (exportImportManager.isRunImport() && exportImportManager.isImportMasterIncluded()) {
+                createMasterRealm = false;
+            }
+
+            if (createMasterRealm) {
+                applianceBootstrap.createMasterRealm(contextPath);
+            }
+            session.getTransaction().commit();
+        } catch (RuntimeException re) {
+            if (session.getTransaction().isActive()) {
+                session.getTransaction().rollback();
+            }
+            throw re;
+        } finally {
+            session.close();
+        }
+
+        if (exportImportManager.isRunImport()) {
+            exportImportManager.runImport();
+        } else {
+            importRealms();
+        }
+
+        importAddUser();
+
+        return exportImportManager;
+    }
+
+
     protected void migrateModel() {
         KeycloakSession session = sessionFactory.create();
         try {
diff --git a/testsuite/integration/src/test/resources/log4j.properties b/testsuite/integration/src/test/resources/log4j.properties
index f093692..c2bc22c 100755
--- a/testsuite/integration/src/test/resources/log4j.properties
+++ b/testsuite/integration/src/test/resources/log4j.properties
@@ -49,7 +49,7 @@ log4j.logger.org.keycloak.connections.jpa.updater.liquibase=${keycloak.liquibase
 
 # Enable to view database updates
 # log4j.logger.org.keycloak.connections.mongo.updater.DefaultMongoUpdaterProvider=debug
-# log4j.logger.org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory=debug
+log4j.logger.org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory=${keycloak.liquibase.logging.level}
 # log4j.logger.org.keycloak.migration.MigrationModelManager=debug
 
 # Enable to view hibernate statistics