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;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import liquibase.Liquibase;
import liquibase.Scope;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.LiquibaseException;
import liquibase.resource.ClassLoaderResourceAccessor;
import liquibase.resource.ResourceAccessor;
import liquibase.ui.LoggerUIService;
import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession;
@ -56,7 +59,9 @@ public class DefaultLiquibaseConnectionProvider implements MapLiquibaseConnectio
public Liquibase getLiquibaseForCustomUpdate(final Connection connection, final String defaultSchema, final String changelogLocation,
final ClassLoader classloader, final String changelogTableName) throws LiquibaseException {
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
String scopeId = enterLiquibaseScope();
try {
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnectionFromPool(connection));
if (defaultSchema != null) {
database.setDefaultSchemaName(defaultSchema);
}
@ -64,6 +69,40 @@ public class DefaultLiquibaseConnectionProvider implements MapLiquibaseConnectio
database.setDatabaseChangeLogTableName(changelogTableName);
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.DatabaseFactory;
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 java.io.File;
import java.io.FileWriter;
@ -88,8 +88,8 @@ public class MapJpaLiquibaseUpdaterProvider implements MapJpaUpdaterProvider {
ThreadLocalSessionContext.setCurrentSession(session);
Writer exportWriter = null;
try {
Liquibase liquibase = getLiquibase(modelType, connection, defaultSchema);
try (Liquibase liquibase = getLiquibase(modelType, connection, defaultSchema)) {
if (file != null) {
exportWriter = new FileWriter(file);
}
@ -146,8 +146,7 @@ public class MapJpaLiquibaseUpdaterProvider implements MapJpaUpdaterProvider {
logger.debug("Validating if database is updated");
ThreadLocalSessionContext.setCurrentSession(session);
try {
Liquibase liquibase = getLiquibase(modelType, connection, defaultSchema);
try (Liquibase liquibase = getLiquibase(modelType, connection, defaultSchema)) {
Status status = validateChangeSet(liquibase, liquibase.getChangeLogFile());
if (status != Status.VALID) {
@ -198,10 +197,14 @@ public class MapJpaLiquibaseUpdaterProvider implements MapJpaUpdaterProvider {
if (modelName.equals("auth-events") || modelName.equals("admin-events"))
modelName = "events";
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
// if database is cockroachdb, use the aggregate changelog (see GHI #11230).
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnectionFromPool(connection));
try {
// if the database is cockroachdb, use the aggregate changelog (see GHI #11230).
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