diff --git a/distribution/server-x-dist/src/main/content/bin/kc.sh b/distribution/server-x-dist/src/main/content/bin/kc.sh
index b3540d65b2..d8960c8bab 100644
--- a/distribution/server-x-dist/src/main/content/bin/kc.sh
+++ b/distribution/server-x-dist/src/main/content/bin/kc.sh
@@ -46,9 +46,10 @@ do
;;
*)
if [[ $1 = --* || ! $1 =~ ^-D.* ]]; then
- CONFIG_ARGS="$CONFIG_ARGS $1"
if [[ "$1" = "start-dev" ]]; then
- CONFIG_ARGS="$CONFIG_ARGS --profile=dev --auto-build"
+ CONFIG_ARGS="$CONFIG_ARGS --profile=dev $1 --auto-build"
+ else
+ CONFIG_ARGS="$CONFIG_ARGS $1"
fi
else
SERVER_OPTS="$SERVER_OPTS $1"
diff --git a/quarkus/README.md b/quarkus/README.md
index 82d3450f5b..271cc29a67 100644
--- a/quarkus/README.md
+++ b/quarkus/README.md
@@ -50,13 +50,13 @@ the HTTP port, run the server in development mode as follows:
To run the server in development mode:
- mvn -f server/pom.xml compile quarkus:dev
+ mvn -f server/pom.xml compile quarkus:dev -Dquarkus.args="start-dev"
You should be able to attach your debugger to port `5005`.
For debugging the build steps, you can suspend the JVM by running:
- mvn -f server/pom.xml -Dsuspend=true compile quarkus:dev
+ mvn -f server/pom.xml -Dsuspend=true compile quarkus:dev -Dquarkus.args="start-dev"
When running using `quarkus:dev` you should be able to do live coding whenever code changes within the `server` module. Changes you make to transient dependencies from the server extension (e.g: services, model, etc) won't be reflected into the running server. However, you can still leverage the hot swapping capabilities from your IDE to make changes at runtime.
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Environment.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Environment.java
index 8095e06623..a3d4dd35ce 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Environment.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Environment.java
@@ -150,11 +150,6 @@ public final class Environment {
return true;
}
- // if running in quarkus:dev mode
- if (ProfileManager.getLaunchMode() == LaunchMode.DEVELOPMENT) {
- return true;
- }
-
return DEV_PROFILE_VALUE.equals(getBuiltTimeProperty(PROFILE).orElse(null));
}
@@ -194,4 +189,8 @@ public final class Environment {
}
})).collect(Collectors.toMap(File::getName, Function.identity()));
}
+
+ public static boolean isQuarkusDevMode() {
+ return ProfileManager.getLaunchMode().equals(LaunchMode.DEVELOPMENT);
+ }
}
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 1f34b76ada..f5a276553d 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
@@ -19,10 +19,8 @@ package org.keycloak.quarkus.runtime;
import static org.keycloak.quarkus.runtime.Environment.isDevProfile;
import static org.keycloak.quarkus.runtime.Environment.getProfileOrDefault;
-import static org.keycloak.quarkus.runtime.cli.Picocli.error;
import static org.keycloak.quarkus.runtime.cli.Picocli.parseAndRun;
-import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -31,11 +29,13 @@ import io.quarkus.runtime.ApplicationLifecycleManager;
import io.quarkus.runtime.Quarkus;
import org.jboss.logging.Logger;
+import org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler;
import org.keycloak.quarkus.runtime.cli.Picocli;
import org.keycloak.common.Version;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;
+import picocli.CommandLine;
/**
*
The main entry point, responsible for initialize and run the CLI as well as start the server.
@@ -59,17 +59,21 @@ public class KeycloakMain implements QuarkusApplication {
parseAndRun(cliArgs);
}
- public static void start(List cliArgs, PrintWriter errorWriter) {
+ public static void start(CommandLine cmd) {
try {
Quarkus.run(KeycloakMain.class, (integer, cause) -> {
if (cause != null) {
- error(cliArgs, errorWriter,
+ ExecutionExceptionHandler exceptionHandler = (ExecutionExceptionHandler) cmd.getExecutionExceptionHandler();
+
+ exceptionHandler.error(cmd.getErr(),
String.format("Failed to start server using profile (%s)", getProfileOrDefault("prod")),
cause.getCause());
}
});
} catch (Throwable cause) {
- error(cliArgs, errorWriter,
+ ExecutionExceptionHandler exceptionHandler = (ExecutionExceptionHandler) cmd.getExecutionExceptionHandler();
+
+ exceptionHandler.error(cmd.getErr(),
String.format("Unexpected error when starting the server using profile (%s)", getProfileOrDefault("prod")),
cause.getCause());
}
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/Messages.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Messages.java
similarity index 78%
rename from quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/Messages.java
rename to quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Messages.java
index 77b2f75291..c37b942ade 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/Messages.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/Messages.java
@@ -15,9 +15,9 @@
* limitations under the License.
*/
-package org.keycloak.quarkus.runtime.configuration.mappers;
+package org.keycloak.quarkus.runtime;
-import org.keycloak.quarkus.runtime.Environment;
+import picocli.CommandLine;
public final class Messages {
@@ -25,11 +25,11 @@ public final class Messages {
}
- static IllegalArgumentException invalidDatabaseVendor(String db, String... availableOptions) {
+ public static IllegalArgumentException invalidDatabaseVendor(String db, String... availableOptions) {
return new IllegalArgumentException("Invalid database vendor [" + db + "]. Possible values are: " + String.join(", ", availableOptions) + ".");
}
- static IllegalArgumentException invalidProxyMode(String mode) {
+ public static IllegalArgumentException invalidProxyMode(String mode) {
return new IllegalArgumentException("Invalid value [" + mode + "] for configuration property [proxy].");
}
@@ -41,4 +41,8 @@ public final class Messages {
builder.append(".");
return new IllegalStateException(builder.toString());
}
+
+ public static void cliExecutionError(CommandLine cmd, String message, Throwable cause) {
+ throw new CommandLine.ExecutionException(cmd, message, cause);
+ }
}
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/ExecutionExceptionHandler.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/ExecutionExceptionHandler.java
index 6aff6b9ac4..ed63c5eb86 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/ExecutionExceptionHandler.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/ExecutionExceptionHandler.java
@@ -17,15 +17,131 @@
package org.keycloak.quarkus.runtime.cli;
+import static org.keycloak.quarkus.runtime.configuration.Configuration.getConfig;
+
+import java.io.PrintWriter;
+import java.nio.file.FileSystemException;
+import java.util.Optional;
+import org.jboss.logging.Logger;
+import org.keycloak.platform.Platform;
+import org.keycloak.quarkus.runtime.Environment;
+import org.keycloak.quarkus.runtime.InitializationException;
+import org.keycloak.quarkus.runtime.Messages;
+import org.keycloak.quarkus.runtime.integration.QuarkusPlatform;
+
+import io.quarkus.runtime.Quarkus;
+import io.smallrye.config.ConfigValue;
import picocli.CommandLine;
import picocli.CommandLine.ParseResult;
-public class ExecutionExceptionHandler implements CommandLine.IExecutionExceptionHandler {
+public final class ExecutionExceptionHandler implements CommandLine.IExecutionExceptionHandler {
+
+ private Logger logger;
+ private boolean verbose;
+
+ ExecutionExceptionHandler() {}
@Override
- public int handleExecutionException(Exception ex, CommandLine commandLine, ParseResult parseResult) {
- commandLine.getErr().println(ex.getMessage());
- commandLine.usage(commandLine.getErr());
- return commandLine.getCommandSpec().exitCodeOnExecutionException();
+ public int handleExecutionException(Exception cause, CommandLine cmd, ParseResult parseResult) {
+ error(cmd.getErr(), "Failed to run '" + parseResult.subcommands().stream()
+ .map(ParseResult::commandSpec)
+ .map(CommandLine.Model.CommandSpec::name)
+ .findFirst()
+ .orElse(Environment.getCommand()) + "' command.", cause);
+ return cmd.getCommandSpec().exitCodeOnExecutionException();
+ }
+
+ public void error(PrintWriter errorWriter, String message, Throwable cause) {
+ if (message != null) {
+ logError(errorWriter, "ERROR: " + message);
+ }
+
+ if (cause != null) {
+ if (cause instanceof InitializationException) {
+ InitializationException initializationException = (InitializationException) cause;
+ if (initializationException.getSuppressed() == null || initializationException.getSuppressed().length == 0) {
+ dumpException(errorWriter, initializationException);
+ } else if (initializationException.getSuppressed().length == 1) {
+ dumpException(errorWriter, initializationException.getSuppressed()[0]);
+ } else {
+ logError(errorWriter, "ERROR: Multiple configuration errors during startup");
+ int counter = 0;
+ for (Throwable inner : initializationException.getSuppressed()) {
+ counter++;
+ logError(errorWriter, "ERROR " + counter);
+ dumpException(errorWriter, inner);
+ }
+ }
+ } else {
+ dumpException(errorWriter, cause);
+ }
+
+ if (!verbose) {
+ logError(errorWriter, "For more details run the same command passing the '--verbose' option. Also you can use '--help' to see the details about the usage of the particular command.");
+ }
+ }
+
+ Quarkus.asyncExit(1);
+ }
+
+ private void dumpException(PrintWriter errorWriter, Throwable cause) {
+ if (verbose) {
+ logError(errorWriter, cause == null ? "Unknown error." : "Error details:", cause);
+ } else {
+ do {
+ if (cause.getMessage() != null) {
+ logError(errorWriter, String.format("ERROR: %s", cause.getMessage()));
+ }
+ printErrorHints(errorWriter, cause);
+ } while ((cause = cause.getCause()) != null);
+ }
+
+ printErrorHints(errorWriter, cause);
+ }
+
+ private void printErrorHints(PrintWriter errorWriter, Throwable cause) {
+ if (cause instanceof FileSystemException) {
+ FileSystemException fse = (FileSystemException) cause;
+ ConfigValue httpsCertFile = getConfig().getConfigValue("kc.https.certificate.file");
+
+ if (fse.getFile().equals(Optional.ofNullable(httpsCertFile.getValue()).orElse(null))) {
+ logError(errorWriter, Messages.httpsConfigurationNotSet().getMessage());
+ }
+ }
+ }
+
+ private void logError(PrintWriter errorWriter, String errorMessage) {
+ logError(errorWriter, errorMessage, null);
+ }
+
+ // The "cause" can be null
+ private void logError(PrintWriter errorWriter, String errorMessage, Throwable cause) {
+ QuarkusPlatform platform = (QuarkusPlatform) Platform.getPlatform();
+ if (platform.isStarted()) {
+ // Can delegate to proper logger once the platform is started
+ if (cause == null) {
+ getLogger().error(errorMessage);
+ } else {
+ getLogger().error(errorMessage, cause);
+ }
+ } else {
+ if (cause == null) {
+ errorWriter.println(errorMessage);
+ } else {
+ errorWriter.println(errorMessage);
+ cause.printStackTrace(errorWriter);
+ }
+ }
+ }
+
+ private Logger getLogger() {
+ if (logger == null) {
+ logger = Logger.getLogger(ExecutionExceptionHandler.class);
+ }
+ return logger;
+ }
+
+ public void setVerbose(boolean verbose) {
+ this.verbose = verbose;
}
}
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 800bddc918..10456e3a09 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
@@ -32,13 +32,19 @@ import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIS
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
-import java.io.PrintWriter;
-import java.nio.file.FileSystemException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Set;
+import java.util.function.UnaryOperator;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import org.jboss.logging.Logger;
import org.keycloak.quarkus.runtime.cli.command.Build;
import org.keycloak.quarkus.runtime.cli.command.Main;
import org.keycloak.quarkus.runtime.cli.command.Start;
@@ -47,11 +53,7 @@ import org.keycloak.common.Profile;
import org.keycloak.quarkus.runtime.configuration.mappers.ConfigCategory;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
import org.keycloak.quarkus.runtime.configuration.KeycloakConfigSourceProvider;
-import org.keycloak.quarkus.runtime.configuration.mappers.Messages;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
-import org.keycloak.platform.Platform;
-import org.keycloak.quarkus.runtime.InitializationException;
-import org.keycloak.quarkus.runtime.integration.QuarkusPlatform;
import org.keycloak.quarkus.runtime.Environment;
import io.smallrye.config.ConfigValue;
@@ -64,8 +66,6 @@ import picocli.CommandLine.Model.ArgGroupSpec;
public final class Picocli {
- private static final Logger logger = Logger.getLogger(Picocli.class);
-
private static final String ARG_SEPARATOR = ";;";
public static final String ARG_PREFIX = "--";
public static final String ARG_SHORT_PREFIX = "-";
@@ -105,7 +105,7 @@ public final class Picocli {
int exitCode = cmd.execute(cliArgs.toArray(new String[0]));
- if (isDevMode()) {
+ if (Environment.isQuarkusDevMode()) {
// do not exit if running in dev mode, otherwise quarkus dev mode will exit when running from IDE
return;
}
@@ -146,7 +146,7 @@ public final class Picocli {
}
private static void runReAugmentation(List cliArgs, CommandLine cmd) {
- if (StartDev.NAME.equals(cliArgs.get(0))) {
+ if (cliArgs.contains(StartDev.NAME)) {
String profile = Environment.getProfile();
if (profile == null) {
@@ -159,13 +159,18 @@ public final class Picocli {
List configArgsList = new ArrayList<>(cliArgs);
- if (!configArgsList.get(0).startsWith("--")) {
- configArgsList.remove(0);
- }
-
configArgsList.remove(AUTO_BUILD_OPTION_LONG);
configArgsList.remove(AUTO_BUILD_OPTION_SHORT);
- configArgsList.add(0, Build.NAME);
+
+ configArgsList.replaceAll(new UnaryOperator() {
+ @Override
+ public String apply(String arg) {
+ if (arg.equals(Start.NAME) || arg.equals(StartDev.NAME)) {
+ return Build.NAME;
+ }
+ return arg;
+ }
+ });
cmd.execute(configArgsList.toArray(new String[0]));
@@ -421,100 +426,10 @@ public final class Picocli {
return parseResult.expandedArgs();
}
- public static void error(List cliArgs, PrintWriter errorWriter, String message, Throwable throwable) {
- logError(errorWriter, "ERROR: " + message);
-
- if (throwable != null) {
- boolean verbose = cliArgs.contains("--verbose") || cliArgs.contains("-v");
-
- if (throwable instanceof InitializationException) {
- InitializationException initializationException = (InitializationException) throwable;
- if (initializationException.getSuppressed() == null || initializationException.getSuppressed().length == 0) {
- dumpException(errorWriter, initializationException, verbose);
- } else if (initializationException.getSuppressed().length == 1) {
- dumpException(errorWriter, initializationException.getSuppressed()[0], verbose);
- } else {
- logError(errorWriter, "ERROR: Multiple configuration errors during startup");
- int counter = 0;
- for (Throwable inner : initializationException.getSuppressed()) {
- counter++;
- logError(errorWriter, "ERROR " + counter);
- dumpException(errorWriter, inner, verbose);
- }
- }
- } else {
- dumpException(errorWriter, throwable, verbose);
- }
-
- if (!verbose) {
- logError(errorWriter, "For more details run the same command passing the '--verbose' option. Also you can use '--help' to see the details about the usage of the particular command.");
- }
- }
-
- System.exit(1);
- }
-
- public static void error(CommandLine cmd, String message, Throwable throwable) {
- error(getCliArgs(cmd), cmd.getErr(), message, throwable);
- }
-
- public static void error(CommandLine cmd, String message) {
- error(getCliArgs(cmd), cmd.getErr(), message, null);
- }
-
public static void println(CommandLine cmd, String message) {
cmd.getOut().println(message);
}
- private static void dumpException(PrintWriter errorWriter, Throwable cause, boolean verbose) {
- if (verbose) {
- logError(errorWriter, "ERROR: Details:", cause);
- } else {
- do {
- if (cause.getMessage() != null) {
- logError(errorWriter, String.format("ERROR: %s", cause.getMessage()));
- }
- printErrorHints(errorWriter, cause);
- } while ((cause = cause.getCause())!= null);
- }
- printErrorHints(errorWriter, cause);
- }
-
- private static void printErrorHints(PrintWriter errorWriter, Throwable cause) {
- if (cause instanceof FileSystemException) {
- FileSystemException fse = (FileSystemException) cause;
- ConfigValue httpsCertFile = getConfig().getConfigValue("kc.https.certificate.file");
-
- if (fse.getFile().equals(Optional.ofNullable(httpsCertFile.getValue()).orElse(null))) {
- logError(errorWriter, Messages.httpsConfigurationNotSet().getMessage());
- }
- }
- }
-
- private static void logError(PrintWriter errorWriter, String errorMessage) {
- logError(errorWriter, errorMessage, null);
- }
-
- // The "cause" can be null
- private static void logError(PrintWriter errorWriter, String errorMessage, Throwable cause) {
- QuarkusPlatform platform = (QuarkusPlatform) Platform.getPlatform();
- if (platform.isStarted()) {
- // Can delegate to proper logger once the platform is started
- if (cause == null) {
- logger.error(errorMessage);
- } else {
- logger.error(errorMessage, cause);
- }
- } else {
- if (cause == null) {
- errorWriter.println(errorMessage);
- } else {
- errorWriter.println(errorMessage);
- cause.printStackTrace();
- }
- }
- }
-
public static String normalizeKey(String key) {
return replaceNonAlphanumericByUnderscores(key).replace('_', '.');
}
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractCommand.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractCommand.java
index 6ffea5b16a..fead68ca73 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractCommand.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractCommand.java
@@ -17,16 +17,15 @@
package org.keycloak.quarkus.runtime.cli.command;
+import static org.keycloak.quarkus.runtime.Messages.cliExecutionError;
+
import org.keycloak.quarkus.runtime.Environment;
-import org.keycloak.quarkus.runtime.configuration.KeycloakConfigSourceProvider;
import picocli.CommandLine;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Spec;
import picocli.CommandLine.Option;
-import static org.keycloak.quarkus.runtime.cli.Picocli.error;
-
public abstract class AbstractCommand {
@Spec
@@ -37,22 +36,15 @@ public abstract class AbstractCommand {
usageHelp = true)
boolean help;
- @Option(names = {"-pf", "--profile"},
- description = "Set the profile. Use 'dev' profile to enable development mode.")
- public void setProfile(String profile) {
- Environment.setProfile(profile);
+ protected void devProfileNotAllowedError(String cmd) {
+ executionError(spec.commandLine(), String.format("You can not '%s' the server using the '%s' configuration profile. Please re-build the server first, using './kc.sh build' for the default production profile, or using '/.kc.sh build --profile=' with a profile more suitable for production.%n", cmd, Environment.DEV_PROFILE_VALUE));
}
- @Option(names = { "-cf", "--config-file" },
- arity = "1",
- description = "Set the path to a configuration file. By default, configuration properties are read from the \"keycloak.properties\" file in the \"conf\" directory.",
- paramLabel = "file",
- scope = CommandLine.ScopeType.INHERIT)
- public void setConfigFile(String path) {
- System.setProperty(KeycloakConfigSourceProvider.KEYCLOAK_CONFIG_FILE_PROP, path);
+ protected void executionError(CommandLine cmd, String message) {
+ executionError(cmd, message, null);
}
- protected void showDevNotAllowedErrorAndExit(String cmd) {
- error(spec.commandLine(), String.format("You can not '%s' the server using the 'dev' configuration profile. Please re-build the server first, using './kc.sh build' for the default production profile, or using '/.kc.sh build --profile=' with a profile more suitable for production.%n", cmd));
+ protected void executionError(CommandLine cmd, String message, Throwable cause) {
+ cliExecutionError(cmd, message, cause);
}
}
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractExportImportCommand.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractExportImportCommand.java
index 7ba6f8c182..170936c64e 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractExportImportCommand.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractExportImportCommand.java
@@ -17,8 +17,6 @@
package org.keycloak.quarkus.runtime.cli.command;
-import static org.keycloak.quarkus.runtime.cli.Picocli.error;
-
import org.keycloak.quarkus.runtime.Environment;
import picocli.CommandLine;
@@ -62,7 +60,7 @@ public abstract class AbstractExportImportCommand extends AbstractCommand implem
System.setProperty("keycloak.migration.provider", "singleFile");
System.setProperty("keycloak.migration.file", toFile);
} else {
- error(spec.commandLine(), "Must specify either --dir or --file options.");
+ executionError(spec.commandLine(), "Must specify either --dir or --file options.");
}
if (realm != null) {
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractStartCommand.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractStartCommand.java
index 716697a50c..4883d1c869 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractStartCommand.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/AbstractStartCommand.java
@@ -29,8 +29,7 @@ public abstract class AbstractStartCommand extends AbstractCommand implements Ru
@Override
public void run() {
doBeforeRun();
- CommandLine cmd = spec.commandLine();
- KeycloakMain.start(cmd.getParseResult().expandedArgs(), cmd.getErr());
+ KeycloakMain.start(spec.commandLine());
}
protected void doBeforeRun() {
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Build.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Build.java
index 58e88e808b..829fccd655 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Build.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Build.java
@@ -17,8 +17,8 @@
package org.keycloak.quarkus.runtime.cli.command;
-import static org.keycloak.quarkus.runtime.Environment.*;
-import static org.keycloak.quarkus.runtime.cli.Picocli.error;
+import static org.keycloak.quarkus.runtime.Environment.getHomePath;
+import static org.keycloak.quarkus.runtime.Environment.isDevMode;
import static org.keycloak.quarkus.runtime.cli.Picocli.println;
import org.keycloak.quarkus.runtime.Environment;
@@ -83,7 +83,7 @@ public final class Build extends AbstractCommand implements Runnable {
println(spec.commandLine(), "\t" + Environment.getCommand() + " show-config\n");
}
} catch (Throwable throwable) {
- error(spec.commandLine(), "Failed to update server configuration.", throwable);
+ executionError(spec.commandLine(), "Failed to update server configuration.", throwable);
} finally {
cleanTempResources();
}
@@ -92,7 +92,7 @@ public final class Build extends AbstractCommand implements Runnable {
private void exitWithErrorIfDevProfileIsSetAndNotStartDev() {
List userInvokedCliArgs = Environment.getUserInvokedCliArgs();
if(Environment.isDevProfile() && !userInvokedCliArgs.contains(StartDev.NAME)) {
- showDevNotAllowedErrorAndExit(Build.NAME);
+ devProfileNotAllowedError(Build.NAME);
}
}
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Main.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Main.java
index 477e53f5ad..792afb8f12 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Main.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Main.java
@@ -19,9 +19,13 @@ package org.keycloak.quarkus.runtime.cli.command;
import static org.keycloak.quarkus.runtime.cli.Picocli.NO_PARAM_LABEL;
+import org.keycloak.quarkus.runtime.Environment;
+import org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler;
+import org.keycloak.quarkus.runtime.configuration.KeycloakConfigSourceProvider;
+
+import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
-import picocli.CommandLine.ScopeType;
@Command(name = "keycloak",
header = {
@@ -63,6 +67,9 @@ import picocli.CommandLine.ScopeType;
})
public final class Main {
+ @CommandLine.Spec
+ CommandLine.Model.CommandSpec spec;
+
@Option(names = "-D=",
description = "Set a Java system property",
order = 0)
@@ -80,7 +87,23 @@ public final class Main {
@Option(names = { "-v", "--verbose" },
description = "Print out error details when running this command.",
- paramLabel = NO_PARAM_LABEL,
- scope = ScopeType.INHERIT)
- Boolean verbose;
+ paramLabel = NO_PARAM_LABEL)
+ public void setVerbose(boolean verbose) {
+ ExecutionExceptionHandler exceptionHandler = (ExecutionExceptionHandler) spec.commandLine().getExecutionExceptionHandler();
+ exceptionHandler.setVerbose(verbose);
+ }
+
+ @Option(names = {"-pf", "--profile"},
+ description = "Set the profile. Use 'dev' profile to enable development mode.")
+ public void setProfile(String profile) {
+ Environment.setProfile(profile);
+ }
+
+ @Option(names = { "-cf", "--config-file" },
+ arity = "1",
+ description = "Set the path to a configuration file. By default, configuration properties are read from the \"keycloak.properties\" file in the \"conf\" directory.",
+ paramLabel = "file")
+ public void setConfigFile(String path) {
+ System.setProperty(KeycloakConfigSourceProvider.KEYCLOAK_CONFIG_FILE_PROP, path);
+ }
}
\ No newline at end of file
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Start.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Start.java
index fb0ed19708..94323ee2fc 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Start.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Start.java
@@ -18,8 +18,8 @@
package org.keycloak.quarkus.runtime.cli.command;
import static org.keycloak.quarkus.runtime.Environment.isDevProfile;
+import static org.keycloak.quarkus.runtime.Environment.setProfile;
import static org.keycloak.quarkus.runtime.cli.Picocli.NO_PARAM_LABEL;
-import static org.keycloak.quarkus.runtime.cli.Picocli.error;
import static org.keycloak.quarkus.runtime.configuration.Configuration.getBuiltTimeProperty;
import org.keycloak.quarkus.runtime.Environment;
@@ -70,7 +70,7 @@ public final class Start extends AbstractStartCommand implements Runnable {
setProfile(currentProfile.orElse(persistedProfile.orElse("prod")));
if (isDevProfile() && (!currentCliArgs.contains(AUTO_BUILD_OPTION_LONG) || !currentCliArgs.contains(AUTO_BUILD_OPTION_SHORT))) {
- showDevNotAllowedErrorAndExit(Start.NAME);
+ devProfileNotAllowedError(Start.NAME);
}
}
}
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/ConfigArgsConfigSource.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/ConfigArgsConfigSource.java
index cc96bd3369..f8889d6beb 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/ConfigArgsConfigSource.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/ConfigArgsConfigSource.java
@@ -55,13 +55,13 @@ public class ConfigArgsConfigSource extends PropertiesConfigSource {
@Override
public String getValue(String propertyName) {
- String value = super.getValue(propertyName.replace('-', '.'));
+ String value = super.getValue(propertyName);
if (value != null) {
return value;
}
- return null;
+ return super.getValue(propertyName.replace('-', '.'));
}
private static Map parseArgument() {
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/DatabasePropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/DatabasePropertyMappers.java
index ffd6a72b5e..bd1f3cb0c4 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/DatabasePropertyMappers.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/DatabasePropertyMappers.java
@@ -7,7 +7,7 @@ import java.util.Optional;
import java.util.function.BiFunction;
import static java.util.Arrays.asList;
-import static org.keycloak.quarkus.runtime.configuration.mappers.Messages.invalidDatabaseVendor;
+import static org.keycloak.quarkus.runtime.Messages.invalidDatabaseVendor;
import static org.keycloak.quarkus.runtime.integration.QuarkusPlatform.addInitializationException;
final class DatabasePropertyMappers {
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HttpPropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HttpPropertyMappers.java
index 20acb07dfe..8b4ac674a3 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HttpPropertyMappers.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/HttpPropertyMappers.java
@@ -3,6 +3,7 @@ package org.keycloak.quarkus.runtime.configuration.mappers;
import io.smallrye.config.ConfigSourceInterceptorContext;
import io.smallrye.config.ConfigValue;
import org.keycloak.quarkus.runtime.Environment;
+import org.keycloak.quarkus.runtime.Messages;
import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider;
import java.io.File;
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ProxyPropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ProxyPropertyMappers.java
index a7c1b782ed..edfada635e 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ProxyPropertyMappers.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ProxyPropertyMappers.java
@@ -7,6 +7,8 @@ import java.util.function.BiFunction;
import static org.keycloak.quarkus.runtime.integration.QuarkusPlatform.addInitializationException;
+import org.keycloak.quarkus.runtime.Messages;
+
final class ProxyPropertyMappers {
private static final String[] possibleProxyValues = {"none", "edge", "reencrypt", "passthrough"};
diff --git a/quarkus/server/src/main/resources/application.properties b/quarkus/server/src/main/resources/application.properties
index 3bceeb7d6b..9dd1924f31 100644
--- a/quarkus/server/src/main/resources/application.properties
+++ b/quarkus/server/src/main/resources/application.properties
@@ -25,3 +25,6 @@ quarkus.arc.ignored-split-packages=org.keycloak.*
# No need to generate dependencies list
quarkus.package.include-dependency-list=false
+
+# we do not want running dev services in distribution
+quarkus.devservices.enabled=false