KEYCLOAK-3141 Fix DB2 and some other DB issues
This commit is contained in:
parent
e2082ce29f
commit
f7a2ad021e
4 changed files with 89 additions and 58 deletions
|
@ -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();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
ExportImportManager[] exportImportManager = new ExportImportManager[1];
|
||||
|
||||
DBLockManager dbLockManager = new DBLockManager(sessionFactory.create());
|
||||
dbLockManager.checkForcedUnlock();
|
||||
DBLockProvider dbLock = dbLockManager.getDBLock();
|
||||
dbLock.waitForLock();
|
||||
try {
|
||||
migrateModel();
|
||||
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
|
||||
|
||||
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;
|
||||
@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();
|
||||
}
|
||||
|
||||
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();
|
||||
} 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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue