Keycloak Onboarding LabChapter VII — Quarkus Distribution Runtime & Bootstrap0/5Contents
Chapter VII

Quarkus Distribution Runtime & Bootstrap

KeycloakMain is the process entry point started by kc.sh/kc.bat: it validates the JVM's thread pool setup, hands CLI arguments to Picocli for command parsing, and then lets Quarkus boot the CDI container. Once the container is up, KeycloakMain.run() pulls the QuarkusKeycloakSessionFactory out of the Arc container, whose constructor is where every SPI's provider factories — assembled at build time by KeycloakRecorder — actually get instantiated and initialized. This closes the loop from earlier modules: every pluggable provider you learned about is wired together right here at server startup.


walkthrough

KeycloakMain.main(String[] args): the real process entry point

quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakMain.java · lines 7198
lines 71–73

The JVM's actual main() first sanity-checks that the common ForkJoinPool was created with Quarkus's thread factory (otherwise SmallRye config loading via those threads can silently use the wrong classloader) and primes virtual-thread parallelism for Infinispan.

lines 76–87

How the Picocli helper is built depends on how the JVM was launched: the packaged kc.sh distribution runs under a RunnerClassLoader, so plain Picocli() is used (its exit() calls System.exit); any other launch path (tests, IDE runs) clones the system properties and overrides exit() to call Quarkus.asyncExit instead, so the cloned properties can be restored afterward without terminating the JVM.

lines 91–97

The real dispatch happens in the main(args, picocli) overload, which turns the array into cliArgs and calls picocli.parseAndRun(cliArgs); the finally block resets System properties back to their pre-launch snapshot so in-process re-invocations (e.g. across tests) don't leak configuration between runs.

    public static void main(String[] args) {        ensureForkJoinPoolThreadFactoryHasBeenSetToQuarkus();        InfinispanUtils.ensureVirtualThreadsParallelism();        Picocli picocli;        Properties clonedProps = null;        if (!(Thread.currentThread().getContextClassLoader() instanceof RunnerClassLoader)) {            clonedProps = (Properties) System.getProperties().clone();            picocli = new Picocli() { // non-script launch case, avoid System.exit                @Override                public void exit(int exitCode) {                    Quarkus.asyncExit(exitCode);                };            };        } else {            picocli = new Picocli();        }        System.setProperty("kc.version", Version.VERSION);        try {            main(args, picocli);        } finally {            if (clonedProps != null) {                reset(clonedProps);            }        }    }
step 1 of 3
    @Override    public int run(String... args) throws Exception {        QuarkusKeycloakApplication application = Arc.container().instance(QuarkusKeycloakApplication.class).get();        if (COMMAND != null) {            QuarkusKeycloakSessionFactory sessionFactory = Arc.container().instance(QuarkusKeycloakSessionFactory.class).get();            COMMAND.onStart(application, sessionFactory);        }        if (hasEarlyExitLaunchMode() || isNonServerMode()) {            // in test mode we exit immediately            // we should be managing this behavior more dynamically depending on the tests requirements (short/long lived)            Quarkus.asyncExit(ApplicationLifecycleManager.getExitCode());        } else {            if (Boolean.getBoolean(KC_SERVER_PRINT_RUNNING)) {                BiConsumer<Void, Throwable> started = (v, t) -> {                    if (t == null) {                        System.out.println("\n" + RUNNING_MESSAGE);                    }                };                application.getBootstrapFuture().ifPresentOrElse(future -> future.whenComplete(started),                        () -> started.accept(null, null));            }            Quarkus.waitForExit();        }        return ApplicationLifecycleManager.getExitCode();    }
quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakMain.java · lines 167192
Figure I · Quarkus calls this QuarkusApplication#run only after the CDI container is fully initialized, so it's the first safe point to pull the already-assembled QuarkusKeycloakSessionFactory out of the Arc container and hand it to the parsed CLI command's onStart callback.
    public QuarkusKeycloakSessionFactory(            Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories,            Map<Class<? extends Provider>, String> defaultProviders,            Map<String, ProviderFactory> preConfiguredProviders,            List<ClasspathThemeProviderFactory.ThemesRepresentation> themes) {        this.provider = defaultProviders;        spis = factories.keySet();        for (Spi spi : spis) {            for (Map<String, Class<? extends ProviderFactory>> factoryClazz : factories.get(spi).values()) {                for (Map.Entry<String, Class<? extends ProviderFactory>> entry : factoryClazz.entrySet()) {                    ProviderFactory factory = preConfiguredProviders.get(entry.getKey());                    if (factory == null) {                        factory = lookupProviderFactory(entry.getValue());                    }                    if (factory instanceof QuarkusJarThemeProviderFactory) {                        ((QuarkusJarThemeProviderFactory) factory).setThemes(themes);                    }                    Config.Scope scope = Config.scope(spi.getName(), factory.getId());                    factory.init(scope);                    factoriesMap.computeIfAbsent(spi.getProviderClass(), k -> new HashMap<>()).put(factory.getId(), factory);                }            }        }    }
quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/integration/QuarkusKeycloakSessionFactory.java · lines 3563
Figure II · This nested loop over every Spi and every registered ProviderFactory class is the concrete moment every provider SPI covered in earlier modules gets instantiated (or pulled from preConfiguredProviders), scoped via Config.scope(spi.getName(), factory.getId()), and initialized with factory.init(scope) before being stored in factoriesMap.
checkpoint

Check your understanding

Answered in place — nothing is graded, everything is explained. 0 / 2 passed

In KeycloakMain.run(), what does the code retrieve from the Arc CDI container and pass to the parsed command's onStart callback?

What happens for each ProviderFactory class discovered under a given Spi inside QuarkusKeycloakSessionFactory's constructor?