-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Add support for applications which immediately exit #284
Comments
@gsmet has pointed out that this would be a prerequisite for writing CLI apps. |
Being able to easily create Quarkus CLIs might be a good way of keeping people for using Go for such tools |
Just as an update, I've been working on a design proposal for this which I hope to have ready sometime next week. |
@dmlloyd Any update on the status of this? No pressure; just highly interested :-) |
I've been on vacation for a few weeks and just got back. I intend to bring #2866 up to date with all the concerns addressed ASAP. |
Any progress or timelines on this? I am highly interested as well. Is there any example code somewhere of what this would look like? |
No but I could spitball a few concepts to see what sticks. The simplest to implement would be to have a user-provided implementation of the proposed @ApplicationScoped // I assume we'll be able to do it this way...
public class MyMainClass implements ExecutionHandler {
@Override
public int run(ExecutionChain chain, ExecutionContext ctxt) throws Exception {
List<String> args = ctxt.getArgumentsAsList();
boolean ok;
// do whatever with args, and decide if everything is OK
// ultimately populate 'ok'
return ok ? 0 : 1
}
} Another option would be to provide a "smart" annotation that could be applied to exactly one method on one application-scoped bean: public class BeanClass {
// ...
@MainMethod
public int myMain(List<String> args) {
// we could allow int or void returns, args as array or list (or none), etc.
doStuff();
return 0; // ok
}
} Share other ideas if you have them! |
I prefer the second option, it seems more clear and coherent with an usual main class. Also, exposing xecutionChain and ExecutionContext is making it too complex. People with basic knowledge of Java may be confused, while there is nothing confusing with @mainmethod and the List args. |
Would there be any interest in cooperation with the picocli project? Picocli has:
|
@geoand That makes sense. Command line applications may want to use Quarkus dependency injection to inject services into their commands and subcommands. Picocli is designed to integrate with dependency injection containers. What I am proposing is to add an extension to Quarkus that provides a picocli Plus of course some documentation for users of the framework that are interested in creating standalone applications with Quarkus. Something very similar to what Micronaut has done. |
👍 |
Would there be interest in a pull request for such a picocli extension? |
@remkop Thanks a lot for the offer to help! |
Interesting! Isn't it enough to simply have a way to start and stop the context? E.g.: class MyCommand implements Runnable {
@Inject
SomeService service;
@Option(names = "-x")
int x;
public void run() { } // business logic here
private static int execute(String[] args) {
try (Context context = new ContextBuilder().create()) {
IFactory factory = new QuarkusFactory(context);
return new picocli.CommandLine(MyCommand.class, factory).execute(args);
}
}
public static void main(String[] args) {
int exitCode = execute(args);
System.exit(exitCode); // optionally call system.exit
}
} |
Not exactly :) For one thing, in Quarkus the main method (and class) is generated since there are a lot of things that need to happen at startup. |
Interesting! Perhaps it is an idea to push that startup work into |
That could be one idea perhaps. @dmlloyd has done all the heavy lifting in this area so he is the best person to comment :) |
Understood. @dmlloyd Does the above look feasible/interesting? An alternative approach is for Quarkus to provide Spring Boot-like |
I don't think it's really feasible for us to do it this way, just because the state of the system is very fragile when So, the idea would be to get a user-provided That said, the branch needs a little TLC to (hopefully) satisfy the plaintiffs who are not happy with it at present; it's on my list. |
Thanks for the clarification. Looking at your comment from a few days earlier where you mentioned some concepts, I like the simplicity of the
|
This is basically exactly what the patch proposes. We generally don't want users calling
Do you mean the bean manager? I think we have some limitations on what you can do there, but maybe a CDI expert like @mkouba should weigh in here...
We'd want it to give an error at compile time if more than one main method is present I think. |
Understood. What about expanding on that and also recognizing Understood about raising a compile error if more than one
Update: I found the docs and it looks like applications will be able to do This is what I imagine a Quarkus&picocli-powered CLI app with subcommands could look like: @Command(name = "foo", subcommands = Bar.class)
class Foo implements Callable<Integer> {
@Inject SomeService service;
@Option(names = "-x") int x;
public Integer call() { } // business logic here
@MainMethod
public int myMain(String[] args) {
BeanManager beanManager = CDI.current().getBeanManager();
picocli.CommandLine.IFactory factory = new QuarkusFactory(beanManager);
int exitCode = new picocli.CommandLine(Foo.class, factory).execute(args);
return exitCode;
}
}
@Command(name = "bar", description = "This is a subcommand of `foo`")
class Bar implements Callable<Integer> {
@Inject SomeOtherService service;
@Option(names = "-y") int y;
public Integer call() { } // business logic here
} |
I don't know that I'd use |
Yes. To be honest I don't have a concrete use case. Perhaps some applications, depending on the command line arguments, need to either exit immediately with some exit status, or start some long running service in the background and leave the JVM up... |
The most natural integration I can think of would be to allow the main method to return some kind of |
Fair enough. Supporting just |
Excited to see that there already is discussion on how an integration with picocli could work. |
How can I help? Any stuff I could do to make it happen faster? |
@dmlloyd Now that Quarkus 0.27 was released, will you be able to spend time on this? |
I'm almost finished with my current task, and this one will be next. |
@dmlloyd So, we can expect having picocli based solution? Thanks |
Doubtful, but I would expect that the Quarkus solution would be able to support picocli based applications. |
As long as NOT using Picocli is not based solely on the "not invented here syndrom", I'm fine with it ;) ! |
@rpelisse this issue is about enabling CLI styled apps, wether piccoli or other cli fwks are used for quarkus cli is a different topic (one we'll start once cli style support is available :) |
I'm interested in helping with this… been in the go "dark" side for a while and have to admit that creating CLIs with things like cobra is quite pleasant and fast compared to what I've seen in the Java world last time I looked. |
@metacosm Slightly off-topic, but if you have any tips on improving picocli based on your experience with cobra I am always interested! |
@remkop sure, I'd need to take another look at picocli, first, though as it's been a while! 😄 |
Superceded by #6499. |
Superceded by #7681 |
Sometimes an application doesn't have any persistent services. Such applications should auto-exit after everything was "started".
A good way to implement this might be for main-method startup build steps to indicate symbolically if they are persistent. Only a handful will be:
Notably, regular thread pools should not be considered persistent.
If no persistent services are started, then the
shutdownRequested
flag should be immediately set, which will cause the main thread to exit cleanly (with no exit code). The shutdown hook will then run, but as the application was already stopped, it will immediately exit with no action taken.The text was updated successfully, but these errors were encountered: