Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document System.exit usage #1857

Merged
merged 3 commits into from
Dec 20, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions docs/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3620,6 +3620,9 @@ fun main(args: Array<String>) {

CAUTION: Older versions of picocli had some limited exit code support where picocli would call `System.exit`, but this is now deprecated.

When an application is not appropriate to call `System.exit`, for example it runs on the caller's process, you can take a different action based on the returned `int`.
ttddyy marked this conversation as resolved.
Show resolved Hide resolved
See <<Usage of `System.exit`>> section for the usecases.
ttddyy marked this conversation as resolved.
Show resolved Hide resolved

=== Generating an Exit Code

`@Command`-annotated classes that implement `Callable` and `@Command`-<<command-methods,annotated methods>> can simply return an `int` or `Integer`, and this value will be returned from `CommandLine.execute`. For example:
Expand Down Expand Up @@ -11401,6 +11404,31 @@ Multi-line text blocks can be used in command and option descriptions, headers a

For more details, see https://www.infoq.com/articles/java-text-blocks/[this article] by Java Language Architect Brian Goetz.

=== Usage of `System.exit`

ttddyy marked this conversation as resolved.
Show resolved Hide resolved
When an application runs as an independent process, `System.exit` returns an exit code to the caller.
On the other hand, when an application runs as part of the caller process, `System.exit` halts the caller process and ends up an abrupt finish.

In such scenario, you need to avoid `System.exit`.

For example, picocli based <<TAB Autocomplete,TAB AutoComplete application>> solves this problem by having link:autocomplete.html#_maven_example[a system property] to determine whether to call `System.exit`.

Another usecase is https://www.mojohaus.org/exec-maven-plugin/[`exec-maven-plugin`] with https://www.mojohaus.org/exec-maven-plugin/java-mojo.html[`exec:java` goal].
ttddyy marked this conversation as resolved.
Show resolved Hide resolved
This goal invokes the target class on the same maven process.
The `System.exit` call finishes maven process bypassing the rest of the maven steps including its error handlings.

In picocli, any exceptions thrown during the `CommandLine.execute` method are captured, printed, and converted to an exit code.
You can check the exit code and perform an appropriate action, such as throwing an exception, instead of calling `System.exit`.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks strange: you are correct that picocli captures any exceptions thrown during the CommandLine.execute method. That is the difference with the CommandLine.parseArgs method. If an application wants to throw an exception when a problem occurs, it should just use parseArgs.

It would be strange to first capture an exception, convert to an error code, and then use that error code to throw another, less informative, exception...
The manual should not recommend that but instead should recommend using parseArgs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to recommend parseArgs and linked to the 9.7. DIY Command Execution section

Then, the caller(maven process) could perform its exception handlings.

[source,java]
----
int exitCode = new CommandLine(new MyCommand()).execute(args);
if (exitCode != ExitCode.OK) {
throw new IllegalStateException("MyCommand failed");
}
----


== Dependency Injection

Expand Down