From b02ff5381b6d0ae46be508bcf23e9098d600eca4 Mon Sep 17 00:00:00 2001
From: Pedro Igor
Date: Thu, 17 Mar 2022 07:44:36 -0300
Subject: [PATCH 1/2] fixing quarkus-logging-json-deployment
---
quarkus/deployment/pom.xml | 4 ----
1 file changed, 4 deletions(-)
diff --git a/quarkus/deployment/pom.xml b/quarkus/deployment/pom.xml
index 13dd38acc1c8..f26b03b475fd 100644
--- a/quarkus/deployment/pom.xml
+++ b/quarkus/deployment/pom.xml
@@ -78,10 +78,6 @@
io.quarkus
quarkus-smallrye-metrics-deployment
-
- io.quarkus
- quarkus-logging-json-deployment
-
io.quarkus
quarkus-junit5-internal
From 41793b8fb120f8010dabd6cf484e58e00a463e6a Mon Sep 17 00:00:00 2001
From: Pedro Igor
Date: Thu, 10 Feb 2022 18:41:23 -0300
Subject: [PATCH 2/2] Removing unnecessary code paths during startup
Closes #10130
---
quarkus/runtime/pom.xml | 4 +-
.../quarkus/runtime/KeycloakClassLoader.java | 42 +++++++++++++++++++
.../quarkus/runtime/KeycloakMain.java | 10 +++--
.../quarkus/runtime/KeycloakRecorder.java | 21 +---------
.../QuarkusJpaConnectionProviderFactory.java | 8 ++--
.../infinispan/CacheManagerFactory.java | 29 +++++++++++--
.../WebAuthnCredentialProviderFactory.java | 9 +++-
7 files changed, 91 insertions(+), 32 deletions(-)
create mode 100644 quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakClassLoader.java
diff --git a/quarkus/runtime/pom.xml b/quarkus/runtime/pom.xml
index 752113f94809..09fe170ea3bb 100644
--- a/quarkus/runtime/pom.xml
+++ b/quarkus/runtime/pom.xml
@@ -80,8 +80,8 @@
quarkus-smallrye-metrics
- io.quarkus
- quarkus-infinispan-client
+ org.wildfly.security
+ wildfly-elytron
io.quarkiverse.vault
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakClassLoader.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakClassLoader.java
new file mode 100644
index 000000000000..507e7f6afa5c
--- /dev/null
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakClassLoader.java
@@ -0,0 +1,42 @@
+/*
+ * 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 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);
+ }
+}
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakMain.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakMain.java
index a0ff2e6b903e..e286431ccd90 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakMain.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakMain.java
@@ -50,8 +50,6 @@
@ApplicationScoped
public class KeycloakMain implements QuarkusApplication {
- private static final Logger LOGGER = Logger.getLogger(KeycloakMain.class);
-
public static void main(String[] args) {
System.setProperty("kc.version", Version.VERSION_KEYCLOAK);
List cliArgs = Picocli.parseArgs(args);
@@ -80,7 +78,11 @@ public static void main(String[] args) {
}
public static void start(ExecutionExceptionHandler errorHandler, PrintWriter errStream) {
+ ClassLoader originalCl = Thread.currentThread().getContextClassLoader();
+
try {
+ Thread.currentThread().setContextClassLoader(new KeycloakClassLoader());
+
Quarkus.run(KeycloakMain.class, (exitCode, cause) -> {
if (cause != null) {
errorHandler.error(errStream,
@@ -98,6 +100,8 @@ public static void start(ExecutionExceptionHandler errorHandler, PrintWriter err
errorHandler.error(errStream,
String.format("Unexpected error when starting the server in (%s) mode", getKeycloakModeFromProfile(getProfileOrDefault("prod"))),
cause.getCause());
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalCl);
}
}
@@ -107,7 +111,7 @@ public static void start(ExecutionExceptionHandler errorHandler, PrintWriter err
@Override
public int run(String... args) throws Exception {
if (isDevProfile()) {
- LOGGER.warnf("Running the server in development mode. DO NOT use this configuration in production.");
+ Logger.getLogger(KeycloakMain.class).warnf("Running the server in development mode. DO NOT use this configuration in production.");
}
int exitCode = ApplicationLifecycleManager.getExitCode();
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakRecorder.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakRecorder.java
index 65b0ea138c1e..c9bc8dd017f9 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakRecorder.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakRecorder.java
@@ -62,17 +62,7 @@ public void configSessionFactory(
public RuntimeValue createCacheInitializer(String config, ShutdownContext shutdownContext) {
try {
- ConfigurationBuilderHolder builder = new ParserRegistry().parse(config);
-
- if (builder.getNamedConfigurationBuilders().get("sessions").clustering().cacheMode().isClustered()) {
- configureTransportStack(builder);
- }
-
- // For Infinispan 10, we go with the JBoss marshalling.
- // TODO: This should be replaced later with the marshalling recommended by infinispan. Probably protostream.
- // See https://infinispan.org/docs/stable/titles/developing/developing.html#marshalling for the details
- builder.getGlobalConfigurationBuilder().serialization().marshaller(new JBossUserMarshaller());
- CacheManagerFactory cacheManagerFactory = new CacheManagerFactory(builder);
+ CacheManagerFactory cacheManagerFactory = new CacheManagerFactory(config);
shutdownContext.addShutdownTask(new Runnable() {
@Override
@@ -91,15 +81,6 @@ public void run() {
}
}
- private void configureTransportStack(ConfigurationBuilderHolder builder) {
- String transportStack = Configuration.getRawValue("kc.cache-stack");
-
- if (transportStack != null) {
- builder.getGlobalConfigurationBuilder().transport().defaultTransport()
- .addProperty("configurationFile", "default-configs/default-jgroups-" + transportStack + ".xml");
- }
- }
-
public void registerShutdownHook(ShutdownContext shutdownContext) {
shutdownContext.addShutdownTask(new Runnable() {
@Override
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/database/jpa/QuarkusJpaConnectionProviderFactory.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/database/jpa/QuarkusJpaConnectionProviderFactory.java
index 8a082b07b26d..32115025ced5 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/database/jpa/QuarkusJpaConnectionProviderFactory.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/database/jpa/QuarkusJpaConnectionProviderFactory.java
@@ -122,9 +122,11 @@ private void addSpecificNamedQueries(KeycloakSession session, Connection connect
try {
Map unitProperties = emf.getProperties();
- unitProperties.entrySet().stream()
- .filter(entry -> entry.getKey().startsWith(QUERY_PROPERTY_PREFIX))
- .forEach(entry -> configureNamedQuery(entry.getKey().substring(QUERY_PROPERTY_PREFIX.length()), entry.getValue().toString(), em));
+ for (Map.Entry entry : unitProperties.entrySet()) {
+ if (entry.getKey().startsWith(QUERY_PROPERTY_PREFIX)) {
+ configureNamedQuery(entry.getKey().substring(QUERY_PROPERTY_PREFIX.length()), entry.getValue().toString(), em);
+ }
+ }
} finally {
JpaUtils.closeEntityManager(em);
}
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/infinispan/CacheManagerFactory.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/infinispan/CacheManagerFactory.java
index 51aa1f2e9bc1..5f977b3f821a 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/infinispan/CacheManagerFactory.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/infinispan/CacheManagerFactory.java
@@ -23,18 +23,21 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.infinispan.configuration.parsing.ConfigurationBuilderHolder;
+import org.infinispan.configuration.parsing.ParserRegistry;
+import org.infinispan.jboss.marshalling.core.JBossUserMarshaller;
import org.infinispan.manager.DefaultCacheManager;
import org.jboss.logging.Logger;
+import org.keycloak.quarkus.runtime.configuration.Configuration;
public class CacheManagerFactory {
- private ConfigurationBuilderHolder config;
+ private String config;
private DefaultCacheManager cacheManager;
private Future cacheManagerFuture;
private ExecutorService executor;
private boolean initialized;
- public CacheManagerFactory(ConfigurationBuilderHolder config) {
+ public CacheManagerFactory(String config) {
this.config = config;
this.executor = createThreadPool();
this.cacheManagerFuture = executor.submit(this::startCacheManager);
@@ -69,7 +72,18 @@ public Thread newThread(Runnable r) {
}
private DefaultCacheManager startCacheManager() {
- return new DefaultCacheManager(config, isStartEagerly());
+ ConfigurationBuilderHolder builder = new ParserRegistry().parse(config);
+
+ if (builder.getNamedConfigurationBuilders().get("sessions").clustering().cacheMode().isClustered()) {
+ configureTransportStack(builder);
+ }
+
+ // For Infinispan 10, we go with the JBoss marshalling.
+ // TODO: This should be replaced later with the marshalling recommended by infinispan. Probably protostream.
+ // See https://infinispan.org/docs/stable/titles/developing/developing.html#marshalling for the details
+ builder.getGlobalConfigurationBuilder().serialization().marshaller(new JBossUserMarshaller());
+
+ return new DefaultCacheManager(builder, isStartEagerly());
}
private boolean isStartEagerly() {
@@ -101,4 +115,13 @@ private void shutdownThreadPool() {
}
}
}
+
+ private void configureTransportStack(ConfigurationBuilderHolder builder) {
+ String transportStack = Configuration.getRawValue("kc.cache-stack");
+
+ if (transportStack != null) {
+ builder.getGlobalConfigurationBuilder().transport().defaultTransport()
+ .addProperty("configurationFile", "default-configs/default-jgroups-" + transportStack + ".xml");
+ }
+ }
}
diff --git a/services/src/main/java/org/keycloak/credential/WebAuthnCredentialProviderFactory.java b/services/src/main/java/org/keycloak/credential/WebAuthnCredentialProviderFactory.java
index ba13af213778..2f31c7171c4f 100644
--- a/services/src/main/java/org/keycloak/credential/WebAuthnCredentialProviderFactory.java
+++ b/services/src/main/java/org/keycloak/credential/WebAuthnCredentialProviderFactory.java
@@ -16,23 +16,30 @@
package org.keycloak.credential;
+import org.keycloak.Config;
import org.keycloak.common.Profile;
import org.keycloak.models.KeycloakSession;
import com.webauthn4j.converter.util.ObjectConverter;
+import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.EnvironmentDependentProviderFactory;
public class WebAuthnCredentialProviderFactory implements CredentialProviderFactory, EnvironmentDependentProviderFactory {
public static final String PROVIDER_ID = "keycloak-webauthn";
- private static ObjectConverter converter = new ObjectConverter();
+ private ObjectConverter converter;
@Override
public CredentialProvider create(KeycloakSession session) {
return new WebAuthnCredentialProvider(session, converter);
}
+ @Override
+ public void init(Config.Scope config) {
+ converter = new ObjectConverter();
+ }
+
@Override
public String getId() {
return PROVIDER_ID;