Removing unnecessary code paths during startup (#10131)

Closes #10130
This commit is contained in:
Pedro Igor 2022-02-15 08:09:14 -03:00 committed by GitHub
parent 909740ca51
commit f3c3bb5001
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 91 additions and 45 deletions

View file

@ -78,19 +78,6 @@
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-metrics-deployment</artifactId> <artifactId>quarkus-smallrye-metrics-deployment</artifactId>
</dependency> </dependency>
<!-- Cross-DC and ISPN client dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-client-deployment</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-gssapi</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-sasl-gs2</artifactId>
</dependency>
<dependency> <dependency>
<groupId>io.quarkiverse.vault</groupId> <groupId>io.quarkiverse.vault</groupId>
<artifactId>quarkus-vault-deployment</artifactId> <artifactId>quarkus-vault-deployment</artifactId>

View file

@ -80,8 +80,8 @@
<artifactId>quarkus-smallrye-metrics</artifactId> <artifactId>quarkus-smallrye-metrics</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>org.wildfly.security</groupId>
<artifactId>quarkus-infinispan-client</artifactId> <artifactId>wildfly-elytron</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkiverse.vault</groupId> <groupId>io.quarkiverse.vault</groupId>

View file

@ -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<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

@ -50,8 +50,6 @@ import io.quarkus.runtime.annotations.QuarkusMain;
@ApplicationScoped @ApplicationScoped
public class KeycloakMain implements QuarkusApplication { public class KeycloakMain implements QuarkusApplication {
private static final Logger LOGGER = Logger.getLogger(KeycloakMain.class);
public static void main(String[] args) { public static void main(String[] args) {
System.setProperty("kc.version", Version.VERSION_KEYCLOAK); System.setProperty("kc.version", Version.VERSION_KEYCLOAK);
List<String> cliArgs = Picocli.parseArgs(args); List<String> cliArgs = Picocli.parseArgs(args);
@ -80,7 +78,11 @@ public class KeycloakMain implements QuarkusApplication {
} }
public static void start(ExecutionExceptionHandler errorHandler, PrintWriter errStream) { public static void start(ExecutionExceptionHandler errorHandler, PrintWriter errStream) {
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,
@ -98,6 +100,8 @@ public class KeycloakMain implements QuarkusApplication {
errorHandler.error(errStream, errorHandler.error(errStream,
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());
} finally {
Thread.currentThread().setContextClassLoader(originalCl);
} }
} }
@ -107,7 +111,7 @@ public class KeycloakMain implements QuarkusApplication {
@Override @Override
public int run(String... args) throws Exception { public int run(String... args) throws Exception {
if (isDevProfile()) { 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(); int exitCode = ApplicationLifecycleManager.getExitCode();

View file

@ -62,17 +62,7 @@ public class KeycloakRecorder {
public RuntimeValue<CacheManagerFactory> createCacheInitializer(String config, ShutdownContext shutdownContext) { public RuntimeValue<CacheManagerFactory> createCacheInitializer(String config, ShutdownContext shutdownContext) {
try { try {
ConfigurationBuilderHolder builder = new ParserRegistry().parse(config); CacheManagerFactory cacheManagerFactory = new CacheManagerFactory(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);
shutdownContext.addShutdownTask(new Runnable() { shutdownContext.addShutdownTask(new Runnable() {
@Override @Override
@ -91,15 +81,6 @@ public class KeycloakRecorder {
} }
} }
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) { public void registerShutdownHook(ShutdownContext shutdownContext) {
shutdownContext.addShutdownTask(new Runnable() { shutdownContext.addShutdownTask(new Runnable() {
@Override @Override

View file

@ -122,9 +122,11 @@ public final class QuarkusJpaConnectionProviderFactory implements JpaConnectionP
try { try {
Map<String, Object> unitProperties = emf.getProperties(); Map<String, Object> unitProperties = emf.getProperties();
unitProperties.entrySet().stream() for (Map.Entry<String, Object> entry : unitProperties.entrySet()) {
.filter(entry -> entry.getKey().startsWith(QUERY_PROPERTY_PREFIX)) if (entry.getKey().startsWith(QUERY_PROPERTY_PREFIX)) {
.forEach(entry -> configureNamedQuery(entry.getKey().substring(QUERY_PROPERTY_PREFIX.length()), entry.getValue().toString(), em)); configureNamedQuery(entry.getKey().substring(QUERY_PROPERTY_PREFIX.length()), entry.getValue().toString(), em);
}
}
} finally { } finally {
JpaUtils.closeEntityManager(em); JpaUtils.closeEntityManager(em);
} }

View file

@ -23,18 +23,21 @@ import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.infinispan.configuration.parsing.ConfigurationBuilderHolder; 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.infinispan.manager.DefaultCacheManager;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.quarkus.runtime.configuration.Configuration;
public class CacheManagerFactory { public class CacheManagerFactory {
private ConfigurationBuilderHolder config; private String config;
private DefaultCacheManager cacheManager; private DefaultCacheManager cacheManager;
private Future<DefaultCacheManager> cacheManagerFuture; private Future<DefaultCacheManager> cacheManagerFuture;
private ExecutorService executor; private ExecutorService executor;
private boolean initialized; private boolean initialized;
public CacheManagerFactory(ConfigurationBuilderHolder config) { public CacheManagerFactory(String config) {
this.config = config; this.config = config;
this.executor = createThreadPool(); this.executor = createThreadPool();
this.cacheManagerFuture = executor.submit(this::startCacheManager); this.cacheManagerFuture = executor.submit(this::startCacheManager);
@ -69,7 +72,18 @@ public class CacheManagerFactory {
} }
private DefaultCacheManager startCacheManager() { 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() { private boolean isStartEagerly() {
@ -101,4 +115,13 @@ public class CacheManagerFactory {
} }
} }
} }
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");
}
}
} }

View file

@ -16,23 +16,30 @@
package org.keycloak.credential; package org.keycloak.credential;
import org.keycloak.Config;
import org.keycloak.common.Profile; import org.keycloak.common.Profile;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import com.webauthn4j.converter.util.ObjectConverter; import com.webauthn4j.converter.util.ObjectConverter;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.EnvironmentDependentProviderFactory; import org.keycloak.provider.EnvironmentDependentProviderFactory;
public class WebAuthnCredentialProviderFactory implements CredentialProviderFactory<WebAuthnCredentialProvider>, EnvironmentDependentProviderFactory { public class WebAuthnCredentialProviderFactory implements CredentialProviderFactory<WebAuthnCredentialProvider>, EnvironmentDependentProviderFactory {
public static final String PROVIDER_ID = "keycloak-webauthn"; public static final String PROVIDER_ID = "keycloak-webauthn";
private static ObjectConverter converter = new ObjectConverter(); private ObjectConverter converter;
@Override @Override
public CredentialProvider create(KeycloakSession session) { public CredentialProvider create(KeycloakSession session) {
return new WebAuthnCredentialProvider(session, converter); return new WebAuthnCredentialProvider(session, converter);
} }
@Override
public void init(Config.Scope config) {
converter = new ObjectConverter();
}
@Override @Override
public String getId() { public String getId() {
return PROVIDER_ID; return PROVIDER_ID;