Summary
Quarkus is one of Java frameworks for microservices development and cloud-native deployment. It is developed as container-first stack, is designed to get along with Kubernetes and can be integrated with GraalVM or HotSpot virtual machines (VM).
This post shows how to install Quarkus with OpenJDK 21 on Devuan 5 and create an example project to serve JSON REST APIs.
Why Quarkus ?
Java was not ready for the cloud-computing era once. It's because Java and its ecosystem were developed primarily for services which were expected to be always active or at least at most time. Once their servers and services were started, they kept memory consumed after some initiation time. Their services were expected not to be stopped or destroyed once started.
In contrast, services in the cloud remarkably depend on virtualization. VMs are frequently created and destroyed in cloud environment.
Thus cloud development and deployment, driven by container VM and kube pods etc., require fast start up to machines.
After many contributions by many, improvement and new encounters with GraalVM etc., Java lit the way to solve the problem at last.
Backed up by such progress, Quarkus has these good points:
- Fast boot time
- Low memory consumption
Environment
- OS: Devuan 5 Daedalus
- based on Debian 12 bookworm
- App Engine: OpenJDK 21
- Project Build and Management: Apache Maven 3 (3.9.5), Gradle 8 (8.3)
- Java Stack: Quarkus 3 (3.4.3)
Tutorial
Suppose you have OpenJDK 21 and Maven which are ready with environment variables PATH
and JAVA_HOME
set.
With Devuan used, my past posts to install Java 21 and Maven will help.
Starting point 💫
My environment was as below:
$ java --version
openjdk 21 2023-09-19
OpenJDK Runtime Environment (build 21+35-2513)
OpenJDK 64-Bit Server VM (build 21+35-2513, mixed mode, sharing)
$ mvn --version
Apache Maven 3.9.5 (57804ffe001d7215b5e7bcb531cf83df38f93546)
Maven home: /(...)/apache-maven-3.9.5
Java version: 21, vendor: Oracle Corporation, runtime: /(...)/jdk-21
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "6.1.0-13-amd64", arch: "amd64", family: "unix"
Create a Quarkus project 🦯
Maven helps to create a project as below:
$ mvn io.quarkus.platform:quarkus-maven-plugin:3.4.3:create \
-Dextensions='resteasy-reactive-jackson' \
-DnoCode \
-DprojectGroupId=com.quarkusrestjsonexample \
-DprojectArtifactId=quarkus-rest-json-example \
-DbuildTool=gradle
The last -DbuildTool=gradle
is optional. I prefer Gradle build.
The result was as below:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- quarkus:3.4.3:create (default-cli) @ standalone-pom ---
[INFO] -----------
[INFO] selected extensions:
- io.quarkus:quarkus-resteasy-reactive-jackson
[INFO]
applying codestarts...
[INFO] 📚 java
🔨 gradle
📦 quarkus
📝 config-properties
🔧 dockerfiles
🔧 gradle-wrapper
[INFO]
-----------
[SUCCESS] ✅ quarkus project has been successfully generated in:
--> /(...)/quarkus-rest-json-example
-----------
[INFO]
[INFO] ========================================================================================
[INFO] Your new application has been created in /(...)/quarkus-rest-json-example
[INFO] Navigate into this directory and launch your application with mvn quarkus:dev
[INFO] Your application will be accessible on http://localhost:8080
[INFO] ========================================================================================
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.209 s
[INFO] Finished at: 2023-10-15T20:38:05+09:00
[INFO] ------------------------------------------------------------------------
Check build dependencies 🔍
Let's go inside the project:
$ cd rest-json-quickstart
You can see implementation 'io.quarkus:quarkus-resteasy-reactive-jackson'
in dependencies
:
$ grep -a5 'dependencies {' build.gradle
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
implementation 'io.quarkus:quarkus-resteasy-reactive-jackson'
implementation 'io.quarkus:quarkus-arc'
testImplementation 'io.quarkus:quarkus-junit5'
}
OK.
Create .java
files in src
✍
There are no .java
files in src
by default:
$ ls src/main/java/
Here we will create two files in src/main/java
: Fruit.java
and FruitResource.java
as bean and resource.
$ nvim src/main/java/{Fruit.java,FruitResource.java}
Write as below in Fruit.java
:
package com.quarkusrestjsonexample;
public class Fruit {
public String name;
public String description;
public Fruit() {
}
public Fruit(String name, String description) {
this.name = name;
this.description = description;
}
}
When you use NeoVim/Vim, you should type :next
after :w
(save) in order to switch files.
Then write as below in FruitResource.java
:
package com.quarkusrestjsonexample;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Set;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
@Path("/fruits")
public class FruitResource {
private Set<Fruit> fruits = Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));
public FruitResource() {
fruits.add(new Fruit("Apple", "Winter fruit"));
fruits.add(new Fruit("Pineapple", "Tropical fruit"));
}
@GET
public Set<Fruit> list() {
return fruits;
}
@POST
public Set<Fruit> add(Fruit fruit) {
fruits.add(fruit);
return fruits;
}
@DELETE
public Set<Fruit> delete(Fruit fruit) {
fruits.removeIf(existingFruit -> existingFruit.name.contentEquals(fruit.name));
return fruits;
}
}
Type :wq
to close NeoVim/Vim.
Run service 🚀
Gradle helps to build it and start service as below:
$ ./gradlew --console=plain quarkusDev
Then your server will start:
Starting a Gradle Daemon (subsequent builds will be faster)
(...)
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-10-15 20:49:36,188 INFO [io.quarkus] (Quarkus Main Thread) quarkus-rest-json-example 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.4.3) started in 1.242s. Listening on: http://localhost:8080
2023-10-15 20:49:36,190 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2023-10-15 20:49:36,191 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, vertx]
Yay 🙌
Conclusion
According to the Gradle output above, access to http://localhost:8080
with your web browser.
You will see:
Why 404 ? It's because there is no definition about @Path("/")
, the root path, in FruitResource.java
. It's OK now, for it can be extended easily.
Then go to /fruits
and you will see 😉
Our Quarkus Web API service is running in good health.