Categories
graalvm maven Native Quarkus

Command-line tools with Quarkus and Picocli

Quarkus 1.4 introduced to us Command mode, Quarkus 1.5 took it one step forward and introduced a new Picocli extension, which makes the development of command-line tools a breeze.

Let’s create one command-line tool that will help us upgrade old Quarkus project to 1.5

Initial setup

We, firstly, need to have some initial project. You can either use https://code.quarkus.io/ to generate a project, in this case, add picocli extension.

Alternatively, you can generate new project with next command:

mvn io.quarkus:quarkus-maven-plugin:1.5.0.Final:create \
    -DprojectGroupId=net.quarkify.qdm \
    -DprojectArtifactId=qdm \
    -DclassName="net.quarkify.qdm.GreetingResource" \
    -Dextension="picocli,io.quarkus:quarkus-jsonb"
cd qdm

qdm stands for Quarkus Dependency Manager. qpm is already used by Qt package manager, so I decided to mix it up a bit.

Existing project

If you want to add extension to your existing project, use next:

./mvnw quarkus:add-extension -Dextensions="picocli,io.quarkus:quarkus-jsonb"

Or add maven extension:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-jsonb</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-picocli</artifactId>
</dependency>

Strip out Rest API

Command-line tool doesn’t require serving any API(well, maybe in some cases, but not in our), so let’s remove this extensions from our project, firstly, remove Resteasy extension(in bold) from maven.

<dependencies>
  <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy</artifactId>
  </dependency>
  <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-junit5</artifactId>
    <scope>test</scope>
  </dependency>
..

Next, remove GreetingResource.java and test folder(unit tests are a good thing to your project, but because we won’t write unit test we can just remove them for now). You can also remove resource/META-INF folder as well.

Disable logs

Add next two lines to application.properties. We want to still see error messages and we assume that our tool won’t be used in a pipe with other tool (e.g if qpm host | curl - will return error it will fail the curl call which is okay for us)

Adding root command

Every middle+ command-line tool developed in Picocli will require root(or top) command. This command will aggregate all the other commands and serve as entry point for parsing our command line

We’ll need to create QdmCommand in root package location

It’s empty Runnable class and it’s okay.

  1. @TopCommand notifies Quarkus that it’s entry point for our CLI tool
  2. @Command is a Picocli interface that marks the current class as a command. You can read more here
    1. mixinStandardHelpOptions specifies that we want Picocli to generate help options for us. This will automatically add --help option
    2. in version we specify current version of app, there’s also versionProvider, but we won’t cover it in this article

You can do next now:

./mvnw clean package -Pnative
cd target/
./qdm-1.0.0-SNAPSHOT-runner --version
1.0.0

Implement upgrade command

Now we have basic skeleton to start implementing specific commands. For this article, we’re only interested in qdm upgrade method. This function will upgrade your Quarkus project to latest version

Here’s simple and complete code:

We have few different options to pass into our upgrade command.

  1. --releaseUrl specifies where to look for latest release, by default it looks for github releases
  2. -v or --version allows you to specify your own version, e.g 1.5.0.Final
  3. -f or --file allows you to specify pom.xml location. By default, it looks for the current folder.

Other logic in class makes a request to GitHub, looks for properties in pom.xml and replaces the required properties. The only thing is that we have GithubRelease.java which showed below

package net.quarkify.qdm.data;

import io.quarkus.runtime.annotations.RegisterForReflection;

@RegisterForReflection
public class GithubRelease {
public String name;

public GithubRelease() {
}

}

It only contains name which is release name.

Add subcommand to main command

We also need to declare our Upgrade command in main, or top command. It can be done via the next additional line for QdmCommand(in bold)

@Command(mixinStandardHelpOptions = true,
        version = "1.0.0",
        subcommands = UpgradeCommand.class
)
public class QdmCommand implements Runnable {

Build native command

Now that we have our CLI tool ready, let’s build it natively:

./mvnw clean package -Pnative

Install on pc

If you want to use your tool on your machine globally, you can do it with the following command:

mv ./target/qdm-1.0.0-SNAPSHOT-runner /usr/local/bin/qdm

Now you can use in any folder, e.g

cd ~
qdm --help

Verify

But is it even working? For this, I have one of old project repos, let’s clone it :

git clone https://github.com/quarkus-course/lecture-cors-test.git
cd lecture-cors-test

Now let’s use our qdm command:

qdm upgrade --help

Result is good, even though we haven’t included help command we still can see available arguments:

Unknown option: '--help'
Usage:
upgrade [-f=] [--releaseUrl=]
[-v=]
-f, --file= location of pom.xml file
--releaseUrl=
-v, --version= Set specific version for upgrade

If you inspect pom.xml you’ll see that current Quarkus version is 1.2.1.Final, let’s fix it

qdm upgrade

Review the xml file again, you’ll see that it’s set to new version, for me it’s 1.3.4.Final. But we already have 1.5.0.Final, we can use -v command for this

qdm upgrade -v 1.5.0.Final

Nice, let’s verify if backend is working

./mvnw quarkus:dev

You should see upgraded Quarkus up and running

In conclusion

We made Quarkus command-line tool which uses Quarkus repo to upgrade Quarkus project to a newer version. Almost like rewriting the C++ compiler with C++.

I wrote previously a few different command-line tools in C++ and Go, hashsc, for example. And can say that writing CLI tools in the favorite language is more than enjoyable.

In the next article, we’ll see how to setup Github Actions to build executables for Ubuntu and macOS.

This is not the end for qdm. I’ll probably implement some more commands and improve existing one. If you want to improve qdm, I’m happy to accept pull requests.

Categories
Quarkus React Swagger

Setting up Swagger with Quarkus and React

Initialize a full-stack app is an easy task. Connect two seamlessly is a bit trickier. You can call /hello endpoint without any Swagger or other libraries. But when you have, say, 20 endpoints to work with, it’s good to standardize your API calls.

This article covers:

  1. More complex than /hello REST API on Quarkus that will be used by our frontend
  2. Setup Swagger both on Quarkus and React
  3. Create Networking React class that will be used to fetch our data
Categories
Java maven Quarkus React

Build, run and deploy React app with Quarkus

If your project needs UI, React probably is a good option for any middle-size service. With Quarkus, it’s super easy to serve your React app.

This article covers:

  1. Setup node and dependencies required for React
  2. Init basic React project
  3. Configure React to serve from Quarkus
  4. Build and watch React project from maven
  5. Deploy minified React on maven package
Categories
Java maven Quarkus Security Vuejs

Simple JWT Token authentication with Quarkus

Every significant app will have security. And you probably opened this article because you’re looking for some simple yet durable solution. What can be simpler yet good enough as JWT Token authorization? Official Quarkus website already covered this topic, but I’ll show the most popular use-case for it, that is, generation of the token when the user logs in. I’ll show you a more abstract solution that you can plug-in to any app and generate a token with a single line of code in your /login method.

I also covered this topic at my Quarkus course in Security section. This articles basically repeats same lesson with additional simplicity

Categories
Java maven Quarkus Vuejs

Build, run and deploy Vuejs app with Quarkus

Many services usually serve some web UI, whether it’s an admin tool, complete portal, or just a single HTML page. Vuejs is a perfect tool that can help you build single-page applications. Why not integrate it tightly with Quarkus?

This article covers:

  1. Setup node and dependencies required for Vuejs
  2. Init basic Vuejs project
  3. Configure Vuejs to serve from Quarkus
  4. Build and watch Vuejs project from maven
  5. Deploy minified Vuejs on maven package