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;