keycloak-uncached

Merge pull request #3446 from mstruk/KEYCLOAK-3767 KEYCLOAK-3767

10/28/2016 10:56:24 AM

Changes

Details

diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AttrsCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AttrsCmd.java
index 958ae27..efa8e25 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AttrsCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AttrsCmd.java
@@ -61,14 +61,14 @@ public class AttrsCmd extends AbstractGlobalOptionsCmd {
 
             if (args != null) {
                 if (args.size() > 1) {
-                    throw new RuntimeException("Invalid option: " + args.get(1));
+                    throw new IllegalArgumentException("Invalid option: " + args.get(1));
                 }
                 attr = args.get(0);
             }
 
             Class type = regType == EndpointType.DEFAULT ? ClientRepresentation.class : (regType == EndpointType.OIDC ? OIDCClientRepresentation.class : null);
             if (type == null) {
-                throw new RuntimeException("Endpoint not supported: " + regType);
+                throw new IllegalArgumentException("Endpoint not supported: " + regType);
             }
             AttributeKey key = attr == null ? new AttributeKey() : new AttributeKey(attr);
 
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCmd.java
index 06594d7..82c4a54 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCmd.java
@@ -23,12 +23,14 @@ import org.jboss.aesh.console.command.CommandException;
 import org.jboss.aesh.console.command.Command;
 import org.jboss.aesh.console.command.CommandResult;
 import org.jboss.aesh.console.command.invocation.CommandInvocation;
-import org.keycloak.client.registration.cli.util.OsUtil;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.List;
 
+import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
+
 /**
  * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
  */
@@ -69,7 +71,7 @@ public class ConfigCmd extends AbstractAuthOptionsCmd implements Command {
                         if (printHelp()) {
                             return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
                         }
-                        throw new RuntimeException("Unknown sub-command: " + cmd);
+                        throw new IllegalArgumentException("Unknown sub-command: " + cmd + suggestHelp());
                     }
                 }
             }
@@ -78,13 +80,17 @@ public class ConfigCmd extends AbstractAuthOptionsCmd implements Command {
                 return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
             }
 
-            throw new RuntimeException("Sub-command required by '" + OsUtil.CMD + " config' - one of: 'credentials', 'truststore', 'initial-token', 'registration-token'");
+            throw new IllegalArgumentException("Sub-command required by '" + CMD + " config' - one of: 'credentials', 'truststore', 'initial-token', 'registration-token'");
 
         } finally {
             commandInvocation.stop();
         }
     }
 
+    protected String suggestHelp() {
+        return EOL + "Try '" + CMD + " help config' for more information";
+    }
+
     protected String help() {
         return usage();
     }
@@ -92,13 +98,13 @@ public class ConfigCmd extends AbstractAuthOptionsCmd implements Command {
     public static String usage() {
         StringWriter sb = new StringWriter();
         PrintWriter out = new PrintWriter(sb);
-        out.println("Usage: " + OsUtil.CMD + " config SUB_COMMAND [ARGUMENTS]");
+        out.println("Usage: " + CMD + " config SUB_COMMAND [ARGUMENTS]");
         out.println();
         out.println("Where SUB_COMMAND is one of: 'credentials', 'truststore', 'initial-token', 'registration-token'");
         out.println();
         out.println();
-        out.println("Use '" + OsUtil.CMD + " help config SUB_COMMAND' for more info.");
-        out.println("Use '" + OsUtil.CMD + " help' for general information and a list of commands.");
+        out.println("Use '" + CMD + " help config SUB_COMMAND' for more info.");
+        out.println("Use '" + CMD + " help' for general information and a list of commands.");
         return sb.toString();
     }
 }
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCredentialsCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCredentialsCmd.java
index fc2fa61..d83f2c4 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCredentialsCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCredentialsCmd.java
@@ -25,6 +25,7 @@ import static org.keycloak.client.registration.cli.util.ConfigUtil.saveTokens;
 import static org.keycloak.client.registration.cli.util.IoUtil.printErr;
 import static org.keycloak.client.registration.cli.util.IoUtil.readSecret;
 import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
 import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
 
@@ -69,6 +70,8 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
             processGlobalOptions();
 
             return process(commandInvocation);
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
         } finally {
             commandInvocation.stop();
         }
@@ -83,7 +86,7 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
 
         // check server
         if (server == null) {
-            throw new RuntimeException("Required option not specified: --server");
+            throw new IllegalArgumentException("Required option not specified: --server");
         }
 
         try {
@@ -93,7 +96,7 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
         }
 
         if (realm == null)
-            throw new RuntimeException("Required option not specified: --realm");
+            throw new IllegalArgumentException("Required option not specified: --realm");
 
         String signedRequestToken = null;
         boolean clientSet = clientId != null;
@@ -122,7 +125,7 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
 
         if (keystore != null) {
             if (secret != null) {
-                throw new RuntimeException("Can't use both --keystore and --secret");
+                throw new IllegalArgumentException("Can't use both --keystore and --secret");
             }
 
             if (!new File(keystore).isFile()) {
@@ -174,6 +177,10 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
         return CommandResult.SUCCESS;
     }
 
+    protected String suggestHelp() {
+        return EOL + "Try '" + CMD + " help config credentials' for more information";
+    }
+
     protected String help() {
         return usage();
     }
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigInitialTokenCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigInitialTokenCmd.java
index 09a757b..0db641e 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigInitialTokenCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigInitialTokenCmd.java
@@ -19,6 +19,7 @@ import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFI
 import static org.keycloak.client.registration.cli.util.ConfigUtil.saveMergeConfig;
 import static org.keycloak.client.registration.cli.util.IoUtil.warnfOut;
 import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
 import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
 
@@ -47,6 +48,8 @@ public class ConfigInitialTokenCmd extends AbstractAuthOptionsCmd implements Com
             }
 
             return process(commandInvocation);
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
         } finally {
             commandInvocation.stop();
         }
@@ -85,13 +88,13 @@ public class ConfigInitialTokenCmd extends AbstractAuthOptionsCmd implements Com
         }
 
         if (args.size() > 1) {
-            throw new RuntimeException("Invalid option: " + args.get(1));
+            throw new IllegalArgumentException("Invalid option: " + args.get(1));
         }
 
         String token = args.size() == 1 ? args.get(0) : null;
 
         if (realm == null) {
-            throw new RuntimeException("Realm not specified");
+            throw new IllegalArgumentException("Realm not specified");
         }
 
         if (token != null && token.startsWith("-")) {
@@ -138,6 +141,10 @@ public class ConfigInitialTokenCmd extends AbstractAuthOptionsCmd implements Com
         return CommandResult.SUCCESS;
     }
 
+    protected String suggestHelp() {
+        return EOL + "Try '" + CMD + " help config initial-token' for more information";
+    }
+
     protected String help() {
         return usage();
     }
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigRegistrationTokenCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigRegistrationTokenCmd.java
index ec01ea6..9e38503 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigRegistrationTokenCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigRegistrationTokenCmd.java
@@ -17,6 +17,7 @@ import java.util.List;
 import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
 import static org.keycloak.client.registration.cli.util.ConfigUtil.saveMergeConfig;
 import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
 import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
 
@@ -44,6 +45,9 @@ public class ConfigRegistrationTokenCmd extends AbstractAuthOptionsCmd implement
             }
 
             return process(commandInvocation);
+
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
         } finally {
             commandInvocation.stop();
         }
@@ -77,21 +81,21 @@ public class ConfigRegistrationTokenCmd extends AbstractAuthOptionsCmd implement
         }
 
         if (args.size() > 1) {
-            throw new RuntimeException("Invalid option: " + args.get(1));
+            throw new IllegalArgumentException("Invalid option: " + args.get(1));
         }
 
         String token = args.size() == 1 ? args.get(0) : null;
 
         if (server == null) {
-            throw new RuntimeException("Required option not specified: --server");
+            throw new IllegalArgumentException("Required option not specified: --server");
         }
 
         if (realm == null) {
-            throw new RuntimeException("Required option not specified: --realm");
+            throw new IllegalArgumentException("Required option not specified: --realm");
         }
 
         if (clientId == null) {
-            throw new RuntimeException("Required option not specified: --client");
+            throw new IllegalArgumentException("Required option not specified: --client");
         }
 
         checkUnsupportedOptions(
@@ -128,6 +132,10 @@ public class ConfigRegistrationTokenCmd extends AbstractAuthOptionsCmd implement
         return CommandResult.SUCCESS;
     }
 
+    protected String suggestHelp() {
+        return EOL + "Try '" + CMD + " help config registration-token' for more information";
+    }
+
     protected String help() {
         return usage();
     }
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigTruststoreCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigTruststoreCmd.java
index acc1ca3..b8f1f34 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigTruststoreCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigTruststoreCmd.java
@@ -17,6 +17,7 @@ import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFI
 import static org.keycloak.client.registration.cli.util.ConfigUtil.saveMergeConfig;
 import static org.keycloak.client.registration.cli.util.IoUtil.readSecret;
 import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
 import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
 
@@ -44,6 +45,9 @@ public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd implements Comma
             }
 
             return process(commandInvocation);
+
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
         } finally {
             commandInvocation.stop();
         }
@@ -77,7 +81,7 @@ public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd implements Comma
         }
 
         if (args.size() > 1) {
-            throw new RuntimeException("Invalid option: " + args.get(1));
+            throw new IllegalArgumentException("Invalid option: " + args.get(1));
         }
 
         String truststore = null;
@@ -105,7 +109,7 @@ public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd implements Comma
         if (!delete) {
 
             if (truststore == null) {
-                throw new RuntimeException("No truststore specified");
+                throw new IllegalArgumentException("No truststore specified");
             }
 
             if (!new File(truststore).isFile()) {
@@ -121,10 +125,10 @@ public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd implements Comma
 
         } else {
             if (truststore != null) {
-                throw new RuntimeException("Option --delete is mutually exclusive with specifying a TRUSTSTORE");
+                throw new IllegalArgumentException("Option --delete is mutually exclusive with specifying a TRUSTSTORE");
             }
             if (trustPass != null) {
-                throw new RuntimeException("Options --trustpass and --delete are mutually exclusive");
+                throw new IllegalArgumentException("Options --trustpass and --delete are mutually exclusive");
             }
             store = null;
             pass = null;
@@ -138,6 +142,10 @@ public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd implements Comma
         return CommandResult.SUCCESS;
     }
 
+    protected String suggestHelp() {
+        return EOL + "Try '" + CMD + " help config truststore' for more information";
+    }
+
     protected String help() {
         return usage();
     }
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/CreateCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/CreateCmd.java
index 49a0d1b..cdecfff 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/CreateCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/CreateCmd.java
@@ -56,6 +56,7 @@ import static org.keycloak.client.registration.cli.util.IoUtil.printErr;
 import static org.keycloak.client.registration.cli.util.IoUtil.readFully;
 import static org.keycloak.client.registration.cli.util.IoUtil.readSecret;
 import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
 import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
 import static org.keycloak.client.registration.cli.util.ParseUtil.mergeAttributes;
@@ -114,25 +115,25 @@ public class CreateCmd extends AbstractAuthOptionsCmd implements Command {
                         case "-s":
                         case "--set": {
                             if (!it.hasNext()) {
-                                throw new RuntimeException("Option " + option + " requires a value");
+                                throw new IllegalArgumentException("Option " + option + " requires a value");
                             }
                             String[] keyVal = parseKeyVal(it.next());
                             attrs.add(new AttributeOperation(SET, keyVal[0], keyVal[1]));
                             break;
                         }
                         default: {
-                            throw new RuntimeException("Unsupported option: " + option);
+                            throw new IllegalArgumentException("Unsupported option: " + option);
                         }
                     }
                 }
             }
 
             if (file == null && attrs.size() == 0) {
-                throw new RuntimeException("No file nor attribute values specified");
+                throw new IllegalArgumentException("No file nor attribute values specified");
             }
 
             if (outputClient && returnClientId) {
-                throw new RuntimeException("Options -o and -i can't be used together");
+                throw new IllegalArgumentException("Options -o and -i are mutually exclusive");
             }
 
             // if --token is specified read it
@@ -211,6 +212,8 @@ public class CreateCmd extends AbstractAuthOptionsCmd implements Command {
 
             return CommandResult.SUCCESS;
 
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
         } finally {
             commandInvocation.stop();
         }
@@ -235,6 +238,9 @@ public class CreateCmd extends AbstractAuthOptionsCmd implements Command {
         return noOptions() && regType == null && file == null && (args == null || args.size() == 0);
     }
 
+    protected String suggestHelp() {
+        return EOL + "Try '" + CMD + " help create' for more information";
+    }
 
     protected String help() {
         return usage();
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/DeleteCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/DeleteCmd.java
index 4c3e0d9..291023a 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/DeleteCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/DeleteCmd.java
@@ -39,6 +39,7 @@ import static org.keycloak.client.registration.cli.util.HttpUtil.doDelete;
 import static org.keycloak.client.registration.cli.util.HttpUtil.urlencode;
 import static org.keycloak.client.registration.cli.util.IoUtil.warnfErr;
 import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
 
 
@@ -61,11 +62,11 @@ public class DeleteCmd extends AbstractAuthOptionsCmd {
             processGlobalOptions();
 
             if (args == null || args.isEmpty()) {
-                throw new RuntimeException("CLIENT not specified");
+                throw new IllegalArgumentException("CLIENT not specified");
             }
 
             if (args.size() > 1) {
-                throw new RuntimeException("Invalid option: " + args.get(1));
+                throw new IllegalArgumentException("Invalid option: " + args.get(1));
             }
 
             String clientId = args.get(0);
@@ -108,6 +109,8 @@ public class DeleteCmd extends AbstractAuthOptionsCmd {
             });
             return CommandResult.SUCCESS;
 
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
         } finally {
             commandInvocation.stop();
         }
@@ -118,6 +121,10 @@ public class DeleteCmd extends AbstractAuthOptionsCmd {
         return noOptions() && (args == null || args.size() == 0);
     }
 
+    protected String suggestHelp() {
+        return EOL + "Try '" + CMD + " help delete' for more information";
+    }
+
     protected String help() {
         return usage();
     }
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/GetCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/GetCmd.java
index 3cb580f..c28fd95 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/GetCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/GetCmd.java
@@ -51,6 +51,7 @@ import static org.keycloak.client.registration.cli.util.IoUtil.warnfErr;
 import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
 import static org.keycloak.client.registration.cli.util.IoUtil.readFully;
 import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
 
 /**
@@ -79,11 +80,11 @@ public class GetCmd extends AbstractAuthOptionsCmd {
             processGlobalOptions();
 
             if (args == null || args.isEmpty()) {
-                throw new RuntimeException("CLIENT not specified");
+                throw new IllegalArgumentException("CLIENT not specified");
             }
 
             if (args.size() > 1) {
-                throw new RuntimeException("Invalid option: " + args.get(1));
+                throw new IllegalArgumentException("Invalid option: " + args.get(1));
             }
 
             String clientId = args.get(0);
@@ -170,6 +171,8 @@ public class GetCmd extends AbstractAuthOptionsCmd {
             }
             return CommandResult.SUCCESS;
 
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
         } finally {
             commandInvocation.stop();
         }
@@ -180,6 +183,10 @@ public class GetCmd extends AbstractAuthOptionsCmd {
         return noOptions() && endpoint == null && (args == null || args.size() == 0);
     }
 
+    protected String suggestHelp() {
+        return EOL + "Try '" + CMD + " help get' for more information";
+    }
+
     protected String help() {
         return usage();
     }
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateCmd.java
index 8a3697c..9192879 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateCmd.java
@@ -62,6 +62,7 @@ import static org.keycloak.client.registration.cli.util.IoUtil.warnfErr;
 import static org.keycloak.client.registration.cli.util.IoUtil.readFully;
 import static org.keycloak.client.registration.cli.util.HttpUtil.APPLICATION_JSON;
 import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
 import static org.keycloak.client.registration.cli.util.ParseUtil.mergeAttributes;
 import static org.keycloak.client.registration.cli.util.ParseUtil.parseFileOrStdin;
@@ -112,7 +113,7 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
             if (args != null) {
                 Iterator<String> it = args.iterator();
                 if (!it.hasNext()) {
-                    throw new RuntimeException("CLIENT_ID not specified");
+                    throw new IllegalArgumentException("CLIENT_ID not specified");
                 }
 
                 clientId = it.next();
@@ -127,7 +128,7 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
                         case "-s":
                         case "--set": {
                             if (!it.hasNext()) {
-                                throw new RuntimeException("Option " + option + " requires a value");
+                                throw new IllegalArgumentException("Option " + option + " requires a value");
                             }
                             String[] keyVal = parseKeyVal(it.next());
                             attrs.add(new AttributeOperation(SET, keyVal[0], keyVal[1]));
@@ -139,14 +140,14 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
                             break;
                         }
                         default: {
-                            throw new RuntimeException("Unsupported option: " + option);
+                            throw new IllegalArgumentException("Unsupported option: " + option);
                         }
                     }
                 }
             }
 
             if (file == null && attrs.size() == 0) {
-                throw new RuntimeException("No file nor attribute values specified");
+                throw new IllegalArgumentException("No file nor attribute values specified");
             }
 
             // We have several options for update:
@@ -318,6 +319,8 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
 
             return CommandResult.SUCCESS;
 
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
         } finally {
             commandInvocation.stop();
         }
@@ -338,6 +341,10 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
         return noOptions() && regType == null && file == null && (args == null || args.size() == 0);
     }
 
+    protected String suggestHelp() {
+        return EOL + "Try '" + CMD + " help update' for more information";
+    }
+
     protected String help() {
         return usage();
     }
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateTokenCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateTokenCmd.java
index c733243..16295f4 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateTokenCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateTokenCmd.java
@@ -45,6 +45,7 @@ import static org.keycloak.client.registration.cli.util.HttpUtil.doPost;
 import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
 import static org.keycloak.client.registration.cli.util.IoUtil.warnfOut;
 import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
 
 /**
@@ -67,7 +68,7 @@ public class UpdateTokenCmd extends AbstractAuthOptionsCmd {
             processGlobalOptions();
 
             if (args == null || args.isEmpty()) {
-                throw new RuntimeException("CLIENT not specified");
+                throw new IllegalArgumentException("CLIENT not specified");
             }
 
             String clientId = args.get(0);
@@ -127,6 +128,8 @@ public class UpdateTokenCmd extends AbstractAuthOptionsCmd {
             //System.out.println("Token updated for client " + clientId);
             return CommandResult.SUCCESS;
 
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
         } finally {
             commandInvocation.stop();
         }
@@ -137,6 +140,10 @@ public class UpdateTokenCmd extends AbstractAuthOptionsCmd {
         return noOptions() && (args == null || args.size() == 0);
     }
 
+    protected String suggestHelp() {
+        return EOL + "Try '" + CMD + " help update-token' for more information";
+    }
+
     protected String help() {
         return usage();
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/AbstractCliTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/AbstractCliTest.java
index ceec8b8..1098053 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/AbstractCliTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/AbstractCliTest.java
@@ -39,6 +39,7 @@ import java.util.Map;
 import java.util.UUID;
 
 import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
+import static org.keycloak.testsuite.cli.KcRegExec.WORK_DIR;
 import static org.keycloak.testsuite.cli.KcRegExec.execute;
 
 /**
@@ -351,7 +352,7 @@ public abstract class AbstractCliTest extends AbstractKeycloakTest {
 
     FileConfigHandler initCustomConfigFile() {
         String filename = UUID.randomUUID().toString() + ".config";
-        File cfgFile = new File(KcRegExec.WORK_DIR + "/" + filename);
+        File cfgFile = new File(WORK_DIR + "/" + filename);
         FileConfigHandler handler = new FileConfigHandler();
         handler.setConfigFile(cfgFile.getAbsolutePath());
         return handler;
@@ -363,7 +364,7 @@ public abstract class AbstractCliTest extends AbstractKeycloakTest {
 
     File initTempFile(String extension, String content) throws IOException {
         String filename = UUID.randomUUID().toString() + extension;
-        File file = new File(KcRegExec.WORK_DIR + "/" + filename);
+        File file = new File(WORK_DIR + "/" + filename);
         if (content != null) {
             OutputStream os = new FileOutputStream(file);
             os.write(content.getBytes(Charset.forName("iso_8859_1")));
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegConfigTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegConfigTest.java
index 473fb1d..b91296c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegConfigTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegConfigTest.java
@@ -8,6 +8,7 @@ import org.keycloak.testsuite.util.TempFileResource;
 
 import java.io.IOException;
 
+import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
 import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.testsuite.cli.KcRegExec.execute;
 
@@ -25,18 +26,21 @@ public class KcRegConfigTest extends AbstractCliTest {
 
             // without --server
             KcRegExec exe = execute("config registration-token --config '" + configFile.getName() + "' ");
-            assertExitCodeAndStreamSizes(exe, 1, 0, 1);
+            assertExitCodeAndStreamSizes(exe, 1, 0, 2);
             Assert.assertEquals("error message", "Required option not specified: --server", exe.stderrLines().get(0));
+            Assert.assertEquals("try help", "Try '" + CMD + " help config registration-token' for more information", exe.stderrLines().get(1));
 
             // without --realm
             exe = execute("config registration-token --config '" + configFile.getName() + "' --server http://localhost:8080/auth");
-            assertExitCodeAndStreamSizes(exe, 1, 0, 1);
+            assertExitCodeAndStreamSizes(exe, 1, 0, 2);
             Assert.assertEquals("error message", "Required option not specified: --realm", exe.stderrLines().get(0));
+            Assert.assertEquals("try help", "Try '" + CMD + " help config registration-token' for more information", exe.stderrLines().get(1));
 
             // without --client
             exe = execute("config registration-token --config '" + configFile.getName() + "' --server http://localhost:8080/auth --realm test");
-            assertExitCodeAndStreamSizes(exe, 1, 0, 1);
+            assertExitCodeAndStreamSizes(exe, 1, 0, 2);
             Assert.assertEquals("error message", "Required option not specified: --client", exe.stderrLines().get(0));
+            Assert.assertEquals("try help", "Try '" + CMD + " help config registration-token' for more information", exe.stderrLines().get(1));
 
             // specify token on cmdline
             exe = execute("config registration-token --config '" + configFile.getName() + "' --server http://localhost:8080/auth --realm test --client my_client NEWTOKEN");
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java
index 7da3a7e..5647ec8 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java
@@ -5,7 +5,6 @@ import org.junit.Test;
 import org.keycloak.client.registration.cli.config.ConfigData;
 import org.keycloak.client.registration.cli.config.FileConfigHandler;
 import org.keycloak.client.registration.cli.config.RealmConfigData;
-import org.keycloak.client.registration.cli.util.OsUtil;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.testsuite.cli.KcRegExec;
 import org.keycloak.testsuite.util.TempFileResource;
@@ -48,51 +47,51 @@ public class KcRegTest extends AbstractCliTest {
         exe = execute("config");
         assertExitCodeAndStreamSizes(exe, 1, 0, 1);
         Assert.assertEquals("error message",
-                "Sub-command required by '" + OsUtil.CMD + " config' - one of: 'credentials', 'truststore', 'initial-token', 'registration-token'",
+                "Sub-command required by '" + CMD + " config' - one of: 'credentials', 'truststore', 'initial-token', 'registration-token'",
                 exe.stderrLines().get(0));
 
         exe = execute("config credentials");
         assertExitCodeAndStdErrSize(exe, 1, 0);
         Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
-        Assert.assertEquals("help message", "Usage: " + OsUtil.CMD + " config credentials --server SERVER_URL --realm REALM [ARGUMENTS]", exe.stdoutLines().get(0));
+        Assert.assertEquals("help message", "Usage: " + CMD + " config credentials --server SERVER_URL --realm REALM [ARGUMENTS]", exe.stdoutLines().get(0));
 
         exe = execute("config initial-token");
         assertExitCodeAndStdErrSize(exe, 1, 0);
         Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
-        Assert.assertEquals("help message", "Usage: " + OsUtil.CMD + " config initial-token --server SERVER --realm REALM [--delete | TOKEN] [ARGUMENTS]", exe.stdoutLines().get(0));
+        Assert.assertEquals("help message", "Usage: " + CMD + " config initial-token --server SERVER --realm REALM [--delete | TOKEN] [ARGUMENTS]", exe.stdoutLines().get(0));
 
         exe = execute("config registration-token");
         assertExitCodeAndStdErrSize(exe, 1, 0);
         Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
-        Assert.assertEquals("help message", "Usage: " + OsUtil.CMD + " config registration-token --server SERVER --realm REALM --client CLIENT [--delete | TOKEN] [ARGUMENTS]", exe.stdoutLines().get(0));
+        Assert.assertEquals("help message", "Usage: " + CMD + " config registration-token --server SERVER --realm REALM --client CLIENT [--delete | TOKEN] [ARGUMENTS]", exe.stdoutLines().get(0));
 
         exe = execute("config truststore");
         assertExitCodeAndStdErrSize(exe, 1, 0);
         Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
-        Assert.assertEquals("help message", "Usage: " + OsUtil.CMD + " config truststore [TRUSTSTORE | --delete] [--trustpass PASSWOD] [ARGUMENTS]", exe.stdoutLines().get(0));
+        Assert.assertEquals("help message", "Usage: " + CMD + " config truststore [TRUSTSTORE | --delete] [--trustpass PASSWOD] [ARGUMENTS]", exe.stdoutLines().get(0));
 
         exe = execute("create");
         assertExitCodeAndStdErrSize(exe, 1, 0);
         Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
-        Assert.assertEquals("help message", "Usage: " + OsUtil.CMD + " create [ARGUMENTS]", exe.stdoutLines().get(0));
+        Assert.assertEquals("help message", "Usage: " + CMD + " create [ARGUMENTS]", exe.stdoutLines().get(0));
         //Assert.assertEquals("error message", "No file nor attribute values specified", exe.stderrLines().get(0));
 
         exe = execute("get");
         assertExitCodeAndStdErrSize(exe, 1, 0);
         Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
-        Assert.assertEquals("help message", "Usage: " + OsUtil.CMD + " get CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
+        Assert.assertEquals("help message", "Usage: " + CMD + " get CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
         //Assert.assertEquals("error message", "CLIENT not specified", exe.stderrLines().get(0));
 
         exe = execute("update");
         assertExitCodeAndStdErrSize(exe, 1, 0);
         Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
-        Assert.assertEquals("help message", "Usage: " + OsUtil.CMD + " update CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
+        Assert.assertEquals("help message", "Usage: " + CMD + " update CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
         //Assert.assertEquals("error message", "No file nor attribute values specified", exe.stderrLines().get(0));
 
         exe = execute("delete");
         assertExitCodeAndStdErrSize(exe, 1, 0);
         Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
-        Assert.assertEquals("help message", "Usage: " + OsUtil.CMD + " delete CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
+        Assert.assertEquals("help message", "Usage: " + CMD + " delete CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
         //Assert.assertEquals("error message", "CLIENT not specified", exe.stderrLines().get(0));
 
         exe = execute("attrs");
@@ -103,7 +102,7 @@ public class KcRegTest extends AbstractCliTest {
         exe = execute("update-token");
         assertExitCodeAndStdErrSize(exe, 1, 0);
         Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
-        Assert.assertEquals("help message", "Usage: " + OsUtil.CMD + " update-token CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
+        Assert.assertEquals("help message", "Usage: " + CMD + " update-token CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
         //Assert.assertEquals("error message", "CLIENT not specified", exe.stderrLines().get(0));
 
         exe = execute("help");
@@ -150,7 +149,7 @@ public class KcRegTest extends AbstractCliTest {
 
         exe = execute("config --help");
         assertExitCodeAndStdErrSize(exe, 0, 0);
-        Assert.assertEquals("stdout first line", "Usage: " + OsUtil.CMD + " config SUB_COMMAND [ARGUMENTS]", exe.stdoutLines().get(0));
+        Assert.assertEquals("stdout first line", "Usage: " + CMD + " config SUB_COMMAND [ARGUMENTS]", exe.stdoutLines().get(0));
 
         exe = execute("config credentials --help");
         assertExitCodeAndStdErrSize(exe, 0, 0);
@@ -208,8 +207,9 @@ public class KcRegTest extends AbstractCliTest {
 
         KcRegExec exe = execute("get my_client --nonexistent");
 
-        assertExitCodeAndStreamSizes(exe, 1, 0, 1);
+        assertExitCodeAndStreamSizes(exe, 1, 0, 2);
         Assert.assertEquals("stderr first line", "Invalid option: --nonexistent", exe.stderrLines().get(0));
+        Assert.assertEquals("try help", "Try '" + CMD + " help get' for more information", exe.stderrLines().get(1));
     }
 
     @Test
@@ -229,8 +229,9 @@ public class KcRegTest extends AbstractCliTest {
          */
         KcRegExec exe = execute("config credentials --realm master --user admin --password admin");
 
-        assertExitCodeAndStreamSizes(exe, 1, 0, 1);
+        assertExitCodeAndStreamSizes(exe, 1, 0, 2);
         Assert.assertEquals("stderr first line", "Required option not specified: --server", exe.stderrLines().get(0));
+        Assert.assertEquals("try help", "Try '" + CMD + " help config credentials' for more information", exe.stderrLines().get(1));
     }
 
     @Test
@@ -240,8 +241,9 @@ public class KcRegTest extends AbstractCliTest {
          */
         KcRegExec exe = execute("config credentials --server " + serverUrl + " --user admin --password admin");
 
-        assertExitCodeAndStreamSizes(exe, 1, 0, 1);
+        assertExitCodeAndStreamSizes(exe, 1, 0, 2);
         Assert.assertEquals("stderr first line", "Required option not specified: --realm", exe.stderrLines().get(0));
+        Assert.assertEquals("try help", "Try '" + CMD + " help config credentials' for more information", exe.stderrLines().get(1));
     }
 
     @Test
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTruststoreTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTruststoreTest.java
index 9a094f3..e3f7729 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTruststoreTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTruststoreTest.java
@@ -4,13 +4,14 @@ import org.junit.Assert;
 import org.junit.Test;
 import org.keycloak.client.registration.cli.config.ConfigData;
 import org.keycloak.client.registration.cli.config.FileConfigHandler;
-import org.keycloak.client.registration.cli.util.ConfigUtil;
 import org.keycloak.testsuite.cli.KcRegExec;
 import org.keycloak.testsuite.util.TempFileResource;
 
 import java.io.File;
 import java.io.IOException;
 
+import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_PATH;
+import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
 import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
 import static org.keycloak.testsuite.cli.KcRegExec.execute;
 
@@ -90,15 +91,17 @@ public class KcRegTruststoreTest extends AbstractCliTest {
         assertExitCodeAndStreamSizes(exe, 0, 0, 0);
 
         exe = execute("config truststore --delete '" + truststore.getAbsolutePath() + "'");
-        assertExitCodeAndStreamSizes(exe, 1, 0, 1);
+        assertExitCodeAndStreamSizes(exe, 1, 0, 2);
         Assert.assertEquals("incompatible", "Option --delete is mutually exclusive with specifying a TRUSTSTORE", exe.stderrLines().get(0));
+        Assert.assertEquals("try help", "Try '" + CMD + " help config truststore' for more information", exe.stderrLines().get(1));
 
         exe = execute("config truststore --delete --trustpass secret");
-        assertExitCodeAndStreamSizes(exe, 1, 0, 1);
+        assertExitCodeAndStreamSizes(exe, 1, 0, 2);
         Assert.assertEquals("no truststore error", "Options --trustpass and --delete are mutually exclusive", exe.stderrLines().get(0));
+        Assert.assertEquals("try help", "Try '" + CMD + " help config truststore' for more information", exe.stderrLines().get(1));
 
         FileConfigHandler cfghandler = new FileConfigHandler();
-        cfghandler.setConfigFile(ConfigUtil.DEFAULT_CONFIG_FILE_PATH);
+        cfghandler.setConfigFile(DEFAULT_CONFIG_FILE_PATH);
         ConfigData config = cfghandler.loadConfig();
         Assert.assertNull("truststore null", config.getTruststore());
         Assert.assertNull("trustpass null", config.getTrustpass());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTest.java
index fba1806..79e6707 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTest.java
@@ -12,6 +12,7 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.util.Arrays;
 
+import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
 import static org.keycloak.testsuite.cli.KcRegExec.execute;
 
 /**
@@ -90,9 +91,9 @@ public class KcRegUpdateTest extends AbstractCliTest {
             // check that using an invalid attribute key is not ignored
             exe = execute("update my_client --nonexisting --config '" + configFile.getName() + "'");
 
-            assertExitCodeAndStreamSizes(exe, 1, 0, 1);
+            assertExitCodeAndStreamSizes(exe, 1, 0, 2);
             Assert.assertEquals("error message", "Unsupported option: --nonexisting", exe.stderrLines().get(0));
-
+            Assert.assertEquals("try help", "Try '" + CMD + " help update' for more information", exe.stderrLines().get(1));
 
 
             // try use incompatible endpoint