Prevent logging changeset on the console for Quarkus

Closes #13126
This commit is contained in:
Alexander Schwartz 2022-07-15 09:50:01 +02:00 committed by Hynek Mlnařík
parent 30b41d02b4
commit b959e5c32a
3 changed files with 101 additions and 18 deletions

View file

@ -18,14 +18,17 @@
package org.keycloak.models.map.storage.jpa.liquibase.connection; package org.keycloak.models.map.storage.jpa.liquibase.connection;
import java.sql.Connection; import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import liquibase.Liquibase; import liquibase.Liquibase;
import liquibase.Scope;
import liquibase.database.Database; import liquibase.database.Database;
import liquibase.database.DatabaseFactory; import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.LiquibaseException; import liquibase.exception.LiquibaseException;
import liquibase.resource.ClassLoaderResourceAccessor; import liquibase.resource.ClassLoaderResourceAccessor;
import liquibase.resource.ResourceAccessor; import liquibase.resource.ResourceAccessor;
import liquibase.ui.LoggerUIService;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
@ -56,14 +59,50 @@ public class DefaultLiquibaseConnectionProvider implements MapLiquibaseConnectio
public Liquibase getLiquibaseForCustomUpdate(final Connection connection, final String defaultSchema, final String changelogLocation, public Liquibase getLiquibaseForCustomUpdate(final Connection connection, final String defaultSchema, final String changelogLocation,
final ClassLoader classloader, final String changelogTableName) throws LiquibaseException { final ClassLoader classloader, final String changelogTableName) throws LiquibaseException {
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection)); String scopeId = enterLiquibaseScope();
if (defaultSchema != null) { try {
database.setDefaultSchemaName(defaultSchema); Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnectionFromPool(connection));
} if (defaultSchema != null) {
ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(classloader); database.setDefaultSchemaName(defaultSchema);
database.setDatabaseChangeLogTableName(changelogTableName); }
ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(classloader);
database.setDatabaseChangeLogTableName(changelogTableName);
logger.debugf("Using changelog file %s and changelogTableName %s", changelogLocation, database.getDatabaseChangeLogTableName()); logger.debugf("Using changelog file %s and changelogTableName %s", changelogLocation, database.getDatabaseChangeLogTableName());
return new Liquibase(changelogLocation, resourceAccessor, database);
return new Liquibase(changelogLocation, resourceAccessor, database) {
@Override
public void close() throws LiquibaseException {
super.close();
exitLiquibaseScope(scopeId);
}
};
} catch (LiquibaseException | RuntimeException ex) {
// When this trows an exception, close the scope here.
// If it returns the Liquibase object, the scope will be closed once the Liquibase object is being closed.
exitLiquibaseScope(scopeId);
throw ex;
}
}
private void exitLiquibaseScope(String scopeId) {
try {
Scope.exit(scopeId);
} catch (Exception e) {
throw new RuntimeException("Failed to exist scope: " + e.getMessage(), e);
}
}
private String enterLiquibaseScope() {
String scopeId;
final Map<String, Object> scopeValues = new HashMap<>();
// Setting the LoggerUIService here prevents Liquibase from logging each change set to the console using java.util.Logging in the Quarkus setup
scopeValues.put(Scope.Attr.ui.name(), new LoggerUIService());
try {
scopeId = Scope.enter(scopeValues);
} catch (Exception e) {
throw new RuntimeException("Failed to initialize Liquibase: " + e.getMessage(), e);
}
return scopeId;
} }
} }

View file

@ -0,0 +1,41 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.map.storage.jpa.liquibase.connection;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.DatabaseException;
import java.sql.Connection;
/**
* Wrapper for JDBC connections retrieved from a connection pool.
* Such a connection would not be closed, but used within the current transaction context.
*
* @author Alexander Schwartz
*/
public class JdbcConnectionFromPool extends JdbcConnection {
public JdbcConnectionFromPool(Connection connection) {
super(connection);
}
@Override
public void close() throws DatabaseException {
rollback();
// do not close the connection here, as connection will be returned to the pool or continued to be used in this session
}
}

View file

@ -20,7 +20,7 @@ package org.keycloak.models.map.storage.jpa.liquibase.updater;
import liquibase.database.Database; import liquibase.database.Database;
import liquibase.database.DatabaseFactory; import liquibase.database.DatabaseFactory;
import liquibase.database.core.CockroachDatabase; import liquibase.database.core.CockroachDatabase;
import liquibase.database.jvm.JdbcConnection; import org.keycloak.models.map.storage.jpa.liquibase.connection.JdbcConnectionFromPool;
import org.keycloak.models.map.storage.jpa.liquibase.connection.MapLiquibaseConnectionProvider; import org.keycloak.models.map.storage.jpa.liquibase.connection.MapLiquibaseConnectionProvider;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
@ -88,8 +88,8 @@ public class MapJpaLiquibaseUpdaterProvider implements MapJpaUpdaterProvider {
ThreadLocalSessionContext.setCurrentSession(session); ThreadLocalSessionContext.setCurrentSession(session);
Writer exportWriter = null; Writer exportWriter = null;
try { try (Liquibase liquibase = getLiquibase(modelType, connection, defaultSchema)) {
Liquibase liquibase = getLiquibase(modelType, connection, defaultSchema);
if (file != null) { if (file != null) {
exportWriter = new FileWriter(file); exportWriter = new FileWriter(file);
} }
@ -146,8 +146,7 @@ public class MapJpaLiquibaseUpdaterProvider implements MapJpaUpdaterProvider {
logger.debug("Validating if database is updated"); logger.debug("Validating if database is updated");
ThreadLocalSessionContext.setCurrentSession(session); ThreadLocalSessionContext.setCurrentSession(session);
try { try (Liquibase liquibase = getLiquibase(modelType, connection, defaultSchema)) {
Liquibase liquibase = getLiquibase(modelType, connection, defaultSchema);
Status status = validateChangeSet(liquibase, liquibase.getChangeLogFile()); Status status = validateChangeSet(liquibase, liquibase.getChangeLogFile());
if (status != Status.VALID) { if (status != Status.VALID) {
@ -198,10 +197,14 @@ public class MapJpaLiquibaseUpdaterProvider implements MapJpaUpdaterProvider {
if (modelName.equals("auth-events") || modelName.equals("admin-events")) if (modelName.equals("auth-events") || modelName.equals("admin-events"))
modelName = "events"; modelName = "events";
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection)); Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnectionFromPool(connection));
// if database is cockroachdb, use the aggregate changelog (see GHI #11230). try {
String changelog = database instanceof CockroachDatabase ? "META-INF/jpa-aggregate-changelog.xml" : "META-INF/jpa-" + modelName + "-changelog.xml"; // if the database is cockroachdb, use the aggregate changelog (see GHI #11230).
return liquibaseProvider.getLiquibaseForCustomUpdate(connection, defaultSchema, changelog, this.getClass().getClassLoader(), "databasechangelog"); String changelog = database instanceof CockroachDatabase ? "META-INF/jpa-aggregate-changelog.xml" : "META-INF/jpa-" + modelName + "-changelog.xml";
return liquibaseProvider.getLiquibaseForCustomUpdate(connection, defaultSchema, changelog, this.getClass().getClassLoader(), "databasechangelog");
} finally {
database.close();
}
} }
@Override @Override