< Back to all posts

Introducing Command Mode

Ever wanted to use Quarkus awesome API’s and full feature set from a command line application ?

Did you need to run a scheduled batch job now and then and not wanting to embed it into your main Quarkus built service ?

3xwzsh

Quarkus has thus far been used to write applications that runs via an endpoint i.e. long running webserver via http or short-lived function in a serverless environment.

In Quarkus 1.4 command mode lets you write apps that run without an endpoint and optionally exits immediately.

This enables you to use Quarkus for writing a whole new style of applications - think command line clients (CLI), batch scripts, console apps, etc.

How to use it

Below is a simple GreetingMain class which uses the traditional GreetingService from all our quickstarts.

import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;

@QuarkusMain    (1)
public class GreetingMain implements QuarkusApplication {
  @Inject (2)
  GreetingService service;

  @Override
  public int run(String... args) throws Exception {   (3)

    if (args.length>0) {
      System.out.println(service.greeting(arg[0]));
    } else {
      System.out.println(service.greeting(""));
    }

    return 0;
 }
}
1 The @QuarkusMain annotation tells Quarkus that this is the main entry point.
2 The run method is invoked once Quarkus starts, and the application stops when it finishes. If you would like to access request scoped beans you can annotate the run method with @ActivateRequestContext. This is useful to write or reuse your existing business logic using i.e. Hibernate Panache Entity beans query methods.

You can add this to a GreetingMain.java and compile to a .jar or to full native (using mvnw package -Dnative) and when run you get something like:

 ./target/getting-started-command-mode-1.0-SNAPSHOT-runner commando
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2020-04-25 00:14:38,999 INFO  [io.quarkus] (main) getting-started-command-mode 1.0-SNAPSHOT (powered by Quarkus 999-SNAPSHOT) started in 0.005s.
2020-04-25 00:14:38,999 INFO  [io.quarkus] (main) Profile prod activated.
2020-04-25 00:14:38,999 INFO  [io.quarkus] (main) Installed features: [cdi]
hello commando
2020-04-25 00:14:38,999 INFO  [io.quarkus] (main) getting-started-command-mode stopped in 0.000s

Clean output

When working with a cli the default console log output can be verbose. For now the best way to turn that off is by setting the following properties:

quarkus.log.level=SEVERE
quarkus.hibernate-orm.log.sql=false
quarkus.banner.enabled=false

These could be set in a custom profile called cli by adding a %cli. prefix.

This has some issues and possible solution are being discussed in issue #8871.

Development mode

Command mode works with quarkus:dev aka. dev-mode.

When you run with mvn quarkus:dev you can add -Dquarkus.args=yourvalue as arguments you want to pass into the command line.

quarkusargs will be split on whitespace and honors escaped quotes to. Thus with mvn quarkus:dev -Dquarkus.args="foo bar \"baz qux\"" the app will start and after end look like this:

foo
bar
baz qux
Quarkus application exited with code 0
Press Enter to restart or Ctrl + C to quit

You can now Press Enter multiple times to force a rerun and if you edited source code Press Enter will trigger build and then restart with no real overhead.

Main methods

As part of adding command mode via a @QuarkusMain annotated class you can now have your own static void main() method. Below snippet is the minimum to run Quarkus from a main method.

static void main(String ...args) {
    Quarkus.run(args);
}

To use it with the above @QuarksMain class would look something like this:

static void main(String ...args) {
    Quarkus.run(GreetingMain.class, args);
}

That is all. This allows you to not only customize start/stop of your Quarks app and what many asked for: ability to launch/debug a Quarkus app directly from an IDE.

You can see a fully working example of these classes in the command-mode quickstart.

Minimal CLI App

It is worth noticing that your cli app can still be serving out an endpoint - in fact, in the default app as we just made the rest endpoint is still starting and running. You just don’t notice it. Quarkus is that fast.

In case you truly want a minimal extension you remove the quarkus-resteasy extension in your pom.xml and put arc instead.

Then nothing else than your Quarkus main class will be run.

What is next ?

You tell us! What would you like to do with a command app with Quarkus ?

For now we are enjoying writing CLI’s but how many others will join us!

Let us know of your ideas at https://github.com/quarkusio/quarkus/issues.