From 27fb8fae5c50885c1e1c98601db35230025b2fb9 Mon Sep 17 00:00:00 2001 From: Steven Hawkins Date: Wed, 11 Feb 2026 10:44:43 -0500 Subject: [PATCH] fix: refining how the junit Keycloak is launched (#46182) closes: #46160 Signed-off-by: Steve Hawkins --- .../keycloak/quarkus/runtime/cli/Picocli.java | 6 ++++- .../src/main/java/org/keycloak/Keycloak.java | 23 +++++++++++++++---- .../it/junit5/extension/CLITestExtension.java | 4 +++- .../basic/BasicTimerProviderFactory.java | 8 ++++--- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java index 41843411344..d0a4b3247da 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java @@ -184,7 +184,7 @@ public class Picocli { // to reuse the previous result either means we need to duplicate the logic in the execute method // or refactor the above logic so that it happens in the command logic // We could also reduce the memory footprint of the ParseResult, but that looks a little hackish - int exitCode = cmd.execute(argArray); + int exitCode = execute(cmd, argArray); exit(exitCode); } catch (ParameterException parEx) { @@ -194,6 +194,10 @@ public class Picocli { } } + protected int execute(CommandLine cmd, String[] argArray) { + return cmd.execute(argArray); + } + public Optional getParsedCommand() { return parsedCommand; } diff --git a/quarkus/tests/junit5/src/main/java/org/keycloak/Keycloak.java b/quarkus/tests/junit5/src/main/java/org/keycloak/Keycloak.java index ccc3b9b6290..78891612585 100644 --- a/quarkus/tests/junit5/src/main/java/org/keycloak/Keycloak.java +++ b/quarkus/tests/junit5/src/main/java/org/keycloak/Keycloak.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import org.keycloak.common.Version; import org.keycloak.common.crypto.FipsMode; @@ -35,6 +36,7 @@ import org.keycloak.platform.Platform; import org.keycloak.quarkus.runtime.Environment; import org.keycloak.quarkus.runtime.KeycloakMain; import org.keycloak.quarkus.runtime.cli.Picocli; +import org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand; import org.keycloak.quarkus.runtime.configuration.Configuration; import org.keycloak.quarkus.runtime.configuration.IgnoredArtifacts; @@ -55,6 +57,7 @@ import io.quarkus.maven.dependency.Dependency; import io.quarkus.maven.dependency.DependencyBuilder; import io.quarkus.runtime.configuration.QuarkusConfigFactory; import org.eclipse.microprofile.config.spi.ConfigProviderResolver; +import picocli.CommandLine; import static java.util.Optional.ofNullable; @@ -206,7 +209,9 @@ public class Keycloak { curated = builder.build().bootstrap(); AugmentAction action = curated.createAugmentor(); Environment.setHomeDir(homeDir); - initSys(args.toArray(String[]::new)); + if (!initSys(args.toArray(String[]::new))) { + return this; + } System.setProperty(Environment.KC_TEST_REBUILD, "true"); StartupAction startupAction = action.createInitialRuntimeApplication(); System.getProperties().remove(Environment.KC_TEST_REBUILD); @@ -215,7 +220,7 @@ public class Keycloak { return this; } catch (Exception cause) { - throw new RuntimeException("Fail to start the server", cause); + throw new RuntimeException("Failed to start the server", cause); } } @@ -326,7 +331,8 @@ public class Keycloak { * Uses a dummy {@link Picocli} to process the args and set system * variables needed to run augmentation */ - public static void initSys(String... args) { + public static boolean initSys(String... args) { + AtomicBoolean result = new AtomicBoolean(); Picocli picocli = new Picocli() { @Override @@ -339,12 +345,21 @@ public class Keycloak { throw new AssertionError(); } + @Override + protected int execute(CommandLine cmd, String[] argArray) { + if (this.getParsedCommand().filter(ac -> ac instanceof AbstractAutoBuildCommand).isPresent()) { + return super.execute(cmd, argArray); + } + return 0; + } + @Override public void exit(int exitCode) { - // do nothing + result.set(exitCode == AbstractAutoBuildCommand.REBUILT_EXIT_CODE); } }; picocli.parseAndRun(List.of(args)); System.setProperty(Environment.KC_CONFIG_BUILT, "true"); + return result.get(); } } diff --git a/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java index e6dbcd47b93..bc7e648dc43 100644 --- a/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java +++ b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java @@ -110,7 +110,9 @@ public class CLITestExtension extends QuarkusMainTestExtension { result = dist.run(List.of(launch.value())); } } else { - Keycloak.initSys(launch == null ? new String[] {} : launch.value()); + if (!Keycloak.initSys(launch == null ? new String[] {} : launch.value())) { + return; + } configureProfile(context); super.beforeEach(context); } diff --git a/services/src/main/java/org/keycloak/timer/basic/BasicTimerProviderFactory.java b/services/src/main/java/org/keycloak/timer/basic/BasicTimerProviderFactory.java index eb4ed9570a9..44e9b9dd5b3 100644 --- a/services/src/main/java/org/keycloak/timer/basic/BasicTimerProviderFactory.java +++ b/services/src/main/java/org/keycloak/timer/basic/BasicTimerProviderFactory.java @@ -49,7 +49,7 @@ public class BasicTimerProviderFactory implements TimerProviderFactory { @Override public void init(Config.Scope config) { transactionTimeout = config.getInt(TRANSACTION_TIMEOUT, 0); - timer = new Timer(); + timer = new Timer(true); } @Override @@ -59,8 +59,10 @@ public class BasicTimerProviderFactory implements TimerProviderFactory { @Override public void close() { - timer.cancel(); - timer = null; + if (timer != null) { + timer.cancel(); + timer = null; + } } @Override