Quarkus QuoteCLI: A Tiny Terminal App with Big Wisdom
Discover how to craft a fast, native command-line application in Java using Quarkus and Mandrel. Complete with CSV-powered inspiration and GraalVM magic.
What if a single command could brighten your day? In this hands-on tutorial, we're building a lightweight command-line application using Quarkus that fetches a random motivational quote from a CSV file and prints it to your terminal. Whether you're compiling code or contemplating life, this little app is a reminder that inspiration doesn’t need a UI. It just needs Java and Quarkus.
Let's get started. (And if you want to jump the gun: Github repository is here too!)
Project Setup: Igniting the Terminal Magic
Fire up your terminal and create a new Quarkus project:
mvn io.quarkus:quarkus-maven-plugin:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=quote-cli \
cd quote-cli
This scaffolds a minimal Quarkus project.
Feed Your Soul: Create the Quotes File
Next, create a new file to hold your motivational gems. Inside src/main/resources
, add a file named quotes.csv
.
mkdir -p src/main/resources
nano src/main/resources/quotes.csv
Paste in a few quotes, each on its own line:
The only way to do great work is to love what you do. - Steve Jobs
Strive not to be a success, but rather to be of value. - Albert Einstein
The future belongs to those who believe in the beauty of their dreams. - Eleanor Roosevelt
Tell me and I forget. Teach me and I remember. Involve me and I learn. - Benjamin Franklin
Be the change that you wish to see in the world. - Mahatma Gandhi
You can always add more later. Think of it as your personal terminal Zen book.
Building the QuoteCLI App
Create src/main/java/org/acme/GreetingCommand.java
with the following:
package org.acme;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;
@QuarkusMain
public class GreetingCommand implements QuarkusApplication {
@Override
public int run(String... args) throws Exception {
List<String> quotes = readQuotesFromCSV("quotes.csv");
if (!quotes.isEmpty()) {
Random random = new Random();
int randomIndex = random.nextInt(quotes.size());
System.out.println("\n💬 " + quotes.get(randomIndex) + "\n");
} else {
System.out.println("No quotes found.");
}
return 0;
}
private List<String> readQuotesFromCSV(String filename) {
List<String> quotes = new ArrayList<>();
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(filename);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = reader.readLine()) != null) {
quotes.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return quotes;
}
}
This small but mighty app:
The
@QuarkusMain
annotation tells Quarkus that this is the main entry point.Loads the
quotes.csv
file from the classpath.Chooses a random quote.
Prints it to the terminal.
Simple. Clean. Enlightening.
Run the App in Dev Mode
Let’s try it out.
Let’s runn the app in Quarkus dev mode:
./mvnw quarkus:dev
Quarkus Dev Mode gives you hot-reload and faster iterations, even in CLI apps.
Then, open another terminal tab and package your app:
./mvnw package
Then run the application as jar.
java -jar target/quarkus-app/quarkus-run.jar
If you want to remove the Quarkus banner and output you have to add the following to your application.properties
quarkus.banner.enabled=false
quarkus.log.level=ERROR
Native Compilation (Optional, but Cool)
If you were impressed by how fast your terminal app ran in dev mode, just wait until you try it as a native executable. But before you jump into the -Dnative
build, let’s talk about the engine that makes it possible and why Quarkus users should know the name Mandrel.
GraalVM is the secret sauce behind Quarkus native images. But not all GraalVMs are created equal.
There are a few GraalVM distributions available: Oracle GraalVM Community Edition (CE), Oracle GraalVM Enterprise Edition (EE), and Mandrel. While Oracle GraalVM CE is the upstream base, Mandrel is the one made with Quarkus in mind.
What is Mandrel?
Mandrel is a downstream distribution of Oracle GraalVM CE, purpose-built to support native Quarkus applications. Think of it as a leaner, meaner GraalVM that strips out everything you don’t need especially features like polyglot support (e.g., running Python, JavaScript, or R in the same VM). Those features are great for general-purpose GraalVM projects, but for Quarkus apps targeting blazing-fast startup and tiny memory footprints, they’re just dead weight.
Why use Mandrel?
Smaller footprint: Mandrel excludes unnecessary GraalVM components, reducing distribution size significantly.
Tailored for Quarkus: It focuses exclusively on what native Quarkus apps need: No fluff.
Security-first: Built from standard OpenJDK without Oracle's non-upstream enhancements, Mandrel stays close to the official OpenJDK release model, which improves compatibility and clarity around security.
Fully compatible: Functionally, Mandrel builds native executables the same way Oracle GraalVM CE does. So your app works the same—just with less overhead.
Make sure to have Mandrel installed. Grab a release from their Github repository.
If you are on MacOS, I suggest putting it into: /Library/Java/JavaVirtualMachines
$ curl -O -J -L "https://github.com/graalvm/mandrel/releases/download/mandrel-24.2.1.0-Final/mandrel-java24-macos-aarch64-24.2.1.0-Final.tar.gz"
$ tar -xf mandrel-java24-macos-aarch64-24.2.1.0-Final.tar.gz
$ export JAVA_HOME="$( pwd )/mandrel-java21-23.1.7.0-Final/Contents/Home"
$ export GRAALVM_HOME="${JAVA_HOME}"
$ export PATH="${JAVA_HOME}/bin:${PATH}"
$ xattr -c -r ./path/to/mandrel
BEFORE we get on with the build, make sure to explicitly add the quotes.csv to the files that are being kept in your application.properties:
quarkus.native.resources.includes=quotes.csv
Now you can build the native image
./mvnw package -Dnative
After a few moments, your app is ready:
./target/quote-cli-1.0.0-SNAPSHOT-native-image-source-jar/quote-cli-1.0.0-SNAPSHOT-runner
Boom. Blazing-fast binary, no JVM needed. You just built your own custom fortune cookie for the terminal.
Bonus: Customizing the Experience
Want to print multiple quotes? Add a --count
option. Or add a --filter "Einstein"
option that only returns quotes from specific authors.
If you want to take this even further, take a look at the Picocli extension which makes it easy to evolve your CLI app with proper flags, help messages, and even nested commands.
Conclusion: Quarkus + Terminal = Joy
Sometimes, the most delightful apps are the smallest. In this tutorial, you built a full-featured command-line application using Quarkus and Picocli. It’s lightning fast, easily extendable, and bundles nicely with your day-to-day tools.
Who said backend devs can’t inspire?
Learn more about: