Removing custom classloader and allow loading drivers at runtime

Closes #13205

Co-authored-by: Brett Lounsbury <brett.lounsbury@nasdaq.com>
This commit is contained in:
Pedro Igor 2023-03-31 09:36:02 -03:00 committed by Václav Muzikář
parent 17c1b853e0
commit d857ea8ec2
16 changed files with 43 additions and 58 deletions

View file

@ -57,6 +57,19 @@ The following is a sample command for a PostgreSQL database.
Be aware that you need to escape characters when invoking commands containing special shell characters such as `;` using the CLI, so you might want to set it in the configuration file instead. Be aware that you need to escape characters when invoking commands containing special shell characters such as `;` using the CLI, so you might want to set it in the configuration file instead.
== Overriding the default JDBC driver
The server uses a default JDBC driver accordingly to the database you chose.
To set a different driver you can set the `db-driver` with the fully qualified class name of the JDBC driver:
<@kc.start parameters="--db postgres --db-driver=my.Driver"/>
Regardless of the driver you set, the default driver is always available at runtime.
Only set this property if you really need to. For instance, when leveraging the capabilities from a JDBC Driver Wrapper for
a specific cloud database service.
== Configuring Unicode support for the database == Configuring Unicode support for the database
Unicode support for all fields depends on whether the database allows VARCHAR and CHAR fields to use the Unicode character set. Unicode support for all fields depends on whether the database allows VARCHAR and CHAR fields to use the Unicode character set.

View file

@ -12,8 +12,7 @@ public class DatabaseOptions {
public static final Option<String> DB_DRIVER = new OptionBuilder<>("db-driver", String.class) public static final Option<String> DB_DRIVER = new OptionBuilder<>("db-driver", String.class)
.category(OptionCategory.DATABASE) .category(OptionCategory.DATABASE)
.hidden() .description("The fully qualified class name of the JDBC driver. If not set, a default driver is set accordingly to the chosen database.")
.defaultValue(Database.getDriver("dev-file", true).get())
.build(); .build();
public static final Option<String> DB = new OptionBuilder<>("db", String.class) public static final Option<String> DB = new OptionBuilder<>("db", String.class)

View file

@ -1,42 +0,0 @@
/*
* Copyright 2021 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.quarkus.runtime;
import java.io.IOException;
import java.net.URL;
import java.sql.Driver;
import java.util.Collections;
import java.util.Enumeration;
public class KeycloakClassLoader extends ClassLoader {
KeycloakClassLoader() {
super(Thread.currentThread().getContextClassLoader());
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
// drivers are going to be loaded lazily, and we avoid loading all available drivers
// see https://github.com/quarkusio/quarkus/pull/7089
if (name.contains(Driver.class.getName())) {
return Collections.emptyEnumeration();
}
return super.getResources(name);
}
}

View file

@ -94,11 +94,7 @@ public class KeycloakMain implements QuarkusApplication {
} }
public static void start(ExecutionExceptionHandler errorHandler, PrintWriter errStream, String[] args) { public static void start(ExecutionExceptionHandler errorHandler, PrintWriter errStream, String[] args) {
ClassLoader originalCl = Thread.currentThread().getContextClassLoader();
try { try {
Thread.currentThread().setContextClassLoader(new KeycloakClassLoader());
Quarkus.run(KeycloakMain.class, (exitCode, cause) -> { Quarkus.run(KeycloakMain.class, (exitCode, cause) -> {
if (cause != null) { if (cause != null) {
errorHandler.error(errStream, errorHandler.error(errStream,
@ -117,8 +113,6 @@ public class KeycloakMain implements QuarkusApplication {
String.format("Unexpected error when starting the server in (%s) mode", getKeycloakModeFromProfile(getProfileOrDefault("prod"))), String.format("Unexpected error when starting the server in (%s) mode", getKeycloakModeFromProfile(getProfileOrDefault("prod"))),
cause.getCause()); cause.getCause());
System.exit(1); System.exit(1);
} finally {
Thread.currentThread().setContextClassLoader(originalCl);
} }
} }

View file

@ -34,6 +34,7 @@ final class DatabasePropertyMappers {
.mapFrom("db") .mapFrom("db")
.to("quarkus.datasource.jdbc.driver") .to("quarkus.datasource.jdbc.driver")
.transformer(DatabasePropertyMappers::getXaOrNonXaDriver) .transformer(DatabasePropertyMappers::getXaOrNonXaDriver)
.paramLabel("driver")
.build(), .build(),
fromOption(DatabaseOptions.DB) fromOption(DatabaseOptions.DB)
.transformer(DatabasePropertyMappers::resolveDatabaseVendor) .transformer(DatabasePropertyMappers::resolveDatabaseVendor)

View file

@ -59,7 +59,7 @@ public class OptionValidationTest {
public void failUnknownOptionWhitespaceSeparatorNotShowingValue(LaunchResult result) { public void failUnknownOptionWhitespaceSeparatorNotShowingValue(LaunchResult result) {
CLIResult cliResult = (CLIResult) result; CLIResult cliResult = (CLIResult) result;
assertEquals("Unknown option: '--db-pasword'\n" + assertEquals("Unknown option: '--db-pasword'\n" +
"Possible solutions: --db-url, --db-url-host, --db-url-database, --db-url-port, --db-url-properties, --db-username, --db-password, --db-schema, --db-pool-initial-size, --db-pool-min-size, --db-pool-max-size, --db\n" + "Possible solutions: --db-driver, --db-url, --db-url-host, --db-url-database, --db-url-port, --db-url-properties, --db-username, --db-password, --db-schema, --db-pool-initial-size, --db-pool-min-size, --db-pool-max-size, --db\n" +
"Try '" + KeycloakDistribution.SCRIPT_CMD + " start --help' for more information on the available options.", cliResult.getErrorOutput()); "Try '" + KeycloakDistribution.SCRIPT_CMD + " start --help' for more information on the available options.", cliResult.getErrorOutput());
} }
@ -68,7 +68,7 @@ public class OptionValidationTest {
public void failUnknownOptionEqualsSeparatorNotShowingValue(LaunchResult result) { public void failUnknownOptionEqualsSeparatorNotShowingValue(LaunchResult result) {
CLIResult cliResult = (CLIResult) result; CLIResult cliResult = (CLIResult) result;
assertEquals("Unknown option: '--db-pasword'\n" + assertEquals("Unknown option: '--db-pasword'\n" +
"Possible solutions: --db-url, --db-url-host, --db-url-database, --db-url-port, --db-url-properties, --db-username, --db-password, --db-schema, --db-pool-initial-size, --db-pool-min-size, --db-pool-max-size, --db\n" + "Possible solutions: --db-driver, --db-url, --db-url-host, --db-url-database, --db-url-port, --db-url-properties, --db-username, --db-password, --db-schema, --db-pool-initial-size, --db-pool-min-size, --db-pool-max-size, --db\n" +
"Try '" + KeycloakDistribution.SCRIPT_CMD + " start --help' for more information on the available options.", cliResult.getErrorOutput()); "Try '" + KeycloakDistribution.SCRIPT_CMD + " start --help' for more information on the available options.", cliResult.getErrorOutput());
} }
@ -77,7 +77,7 @@ public class OptionValidationTest {
public void failWithFirstOptionOnMultipleUnknownOptions(LaunchResult result) { public void failWithFirstOptionOnMultipleUnknownOptions(LaunchResult result) {
CLIResult cliResult = (CLIResult) result; CLIResult cliResult = (CLIResult) result;
assertEquals("Unknown option: '--db-pasword'\n" + assertEquals("Unknown option: '--db-pasword'\n" +
"Possible solutions: --db-url, --db-url-host, --db-url-database, --db-url-port, --db-url-properties, --db-username, --db-password, --db-schema, --db-pool-initial-size, --db-pool-min-size, --db-pool-max-size, --db\n" + "Possible solutions: --db-driver, --db-url, --db-url-host, --db-url-database, --db-url-port, --db-url-properties, --db-username, --db-password, --db-schema, --db-pool-initial-size, --db-pool-min-size, --db-pool-max-size, --db\n" +
"Try '" + KeycloakDistribution.SCRIPT_CMD + " start --help' for more information on the available options.", cliResult.getErrorOutput()); "Try '" + KeycloakDistribution.SCRIPT_CMD + " start --help' for more information on the available options.", cliResult.getErrorOutput());
} }
} }

View file

@ -13,6 +13,8 @@ Options:
Database: Database:
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>

View file

@ -32,6 +32,8 @@ Storage (Experimental):
Database: Database:
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>

View file

@ -13,6 +13,8 @@ Options:
Database: Database:
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>

View file

@ -32,6 +32,8 @@ Storage (Experimental):
Database: Database:
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>

View file

@ -32,6 +32,8 @@ Database:
--db <vendor> The database vendor. Possible values are: dev-file, dev-mem, mariadb, mssql, --db <vendor> The database vendor. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres. Default: dev-file.
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>

View file

@ -95,6 +95,8 @@ Database:
--db <vendor> The database vendor. Possible values are: dev-file, dev-mem, mariadb, mssql, --db <vendor> The database vendor. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres. Default: dev-file.
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>

View file

@ -38,6 +38,8 @@ Database:
--db <vendor> The database vendor. Possible values are: dev-file, dev-mem, mariadb, mssql, --db <vendor> The database vendor. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres. Default: dev-file.
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>

View file

@ -101,6 +101,8 @@ Database:
--db <vendor> The database vendor. Possible values are: dev-file, dev-mem, mariadb, mssql, --db <vendor> The database vendor. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres. Default: dev-file.
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>

View file

@ -22,6 +22,8 @@ Options:
Database: Database:
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>

View file

@ -41,6 +41,8 @@ Storage (Experimental):
Database: Database:
--db-driver <driver> The fully qualified class name of the JDBC driver. If not set, a default
driver is set accordingly to the chosen database.
--db-password <password> --db-password <password>
The password of the database user. The password of the database user.
--db-pool-initial-size <size> --db-pool-initial-size <size>