I'm in the process of updating from picocli 3.9.6 to 4.2.0, and I'm running into an issue when replacing old deprecated calls with the new versions.
In my original version, I had a code block like this:
try {
return commandLine.parseWithHandlers(
new RunLast().useOut(ps),
new ExceptionHandler(),
args);
}
catch(Exception e) {
// handle exceptions
}
The ExceptionHandler
handles both parameter and execution exceptions -- both are rethrown, but parameter exceptions get the help text added to the exception text. The catch would get hit in cases where, e.g., a command was given bad args. The catch would ensure the error was printed in the UI.
I attempted to update it like this:
try {
commandLine.setOut(pw);
ExceptionHandler handler = new ExceptionHandler();
commandLine.setExecutionExceptionHandler(handler);
commandLine.setParameterExceptionHandler(handler);
commandLine.execute(args);
return commandLine.getExecutionResult();
}
catch(Exception e) {
// handle exceptions
}
With this new version, exceptions are thrown as before, but they are no longer caught by the catch block after being rethrown by the ExceptionHandler
. How can I catch these exceptions?
One of the changes in picocli 4.x is the new execution framework. The user manual has a section on migration that may be useful.
By design, the CommandLine::execute
method never throws an exception. So there is no need to surround the call to CommandLine::execute
with a try/catch
block (unless you need to catch an Error
or Throwable
).
Instead, you can optionally specify custom exception handlers, like you already do in your example. These exception handlers is where you can show an error message to the users. (Perhaps a combination of what was in the previous ExceptionHandler and the logic that previously was in the catch
block.)
The ParameterExceptionHandler
is invoked when the user provided invalid input. The default handler shows an error message, may suggest alternative spellings for options or subcommands that look like a typo, and finally displays the usage help message. The Handling Errors section of the user manual has an example ShortErrorMessageHandler
that may be useful when the usage help message is so long that it obscures the error message.
The ExecutionExceptionHandler
is invoked when the business logic throws an exception. The default handler just rethrows the exception, which results in a stack trace being printed. The Business Logic Exceptions section of the user manual shows an alternative.
It sounds like you need a custom ExecutionExceptionHandler
that prints a stack trace followed by the usage help message.