Press "Enter" to skip to content

Quarkus – A New Age of Modern Java Frameworks is Here

If you’ve seen some of my talks, or read some of the articles, you probably already know that I’m not a big fan of frameworks in general – but I learned how to be good friends with them.

However, regardless of the fact if you like frameworks or not, Quarkus brings some worthwhile innovation to the table.

So, let’s ignore the cheesy “Supersonic Subatomic Java” line for a while, and let’s get down to the nitty-gritty, see main Quarkus features, and run a trivial hello-world application.

Quarkus Overview

One of the official elevator pitches states:

Quarkus is a Kubernetes Native Java framework tailored for GraalVM and HotSpot, crafted from best-of-breed Java libraries and standards.

Which sums it up pretty neatly. However, since Quarkus was build from scratch, it’s important to underline that it’s not constrained by backward compatibility which allowed it to fully embrace technologies like containerization or native images.

What’s more, it reuses widely-established standards like CDI, JAX-RS, JPA, JTA, etc. so no need to worry about relearning everything from scratch… again.

GraalVM Support

Thanks to the GraalVM compatibility, Quarkus achieves impressive startup times and RSS memory consumption.

Quarkus not only runs correctly on GraalVM but also embraces the integration by providing dedicated tooling.

If you want to generate a GraalVM native image, there’s no need to manually configure and maintain GraalVM distribution. You can simply supply an extra flag to Maven build and then let the plugin use a Dockerized GraalVM behind the scenes:

mvn package -Pnative -Dquarkus.native.container-build=true

That’s incredibly convenient.

What’s more, Quarkus provides an extension framework that makes GraalVM configuration a smooth experience for extensions creators. Making things GraalVM-compatible can be demanding, but luckily there’s quite an impressive list of already existing extensions.

If you want to see how it looks like, you can check out an extension I developed – quarkus-hazelcast-client.

Now, let’s have a look at some interesting Quarkus features.

Build-time Augmentation

Build-time augmentation is an extra build step used for processing metadata, config parsing, and any other logic that would normally be needed to perform at startup time. The resulting bytecode gets recorded and reused on the actual application startup.

Pushing as much as possible to build-time, makes it possible to achieve impressive startup times, declutter memory, and in some cases to fail-fast before even running the application.

Hot-Reload

If you run your application using the mvn compile quarkus:dev incantation, it will restart seamlessly after detecting a change before serving an HTTP request. Thanks to the build-time augmentation, the whole reload often takes less than a second.

Docker-friendliness

Quarkus keeps all jar dependencies outside the main jar, which makes it possible to leverage Docker layer caching – if dependencies don’t change, the layer containing dependencies can be reused provided your Dockerfile is configured properly:

COPY target/lib/* /deployments/lib/
COPY target/*-runner.jar /deployments/app.jar

I bet now you’d like to try it out on your own – let’s try the above out in a small hello-world application.

Quickstart Guide

You can get started immediately by using http://code.quarkus.io/ which allows you to download a preconfigured project.

This gives us a baseline with a familiar structure.

You can find it on GitHub as well.

Besides the autogenerated hello-world application, we can notice a few nice touches like .dockerignore, .gitignore, and Docker image files which make our application Docker-ready since the beginning.

In order to give it a try, we can just type mvn compile quarkus:dev

The application starts in ~1.5s:

Listening for transport dt_socket at address: 5005
__ ____ __ _____ ___ __ ____ ______ 
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ 
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 
2021-08-26 08:33:36,498 INFO [io.quarkus] (Quarkus Main Thread) quarkus-hello 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.1.3.Final) started in 1.678s. Listening on: http://localhost:8080
2021-08-26 08:33:36,502 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2021-08-26 08:33:36,503 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy, smallrye-context-propagation]

and is ready to accept requests:

> curl -X GET "localhost:8080/hello"
hello%

However, here comes one of the Quarkus highlights.

Find the HelloResource class, change the return value to the value of your choice (I decided to move forward with “hello2”), then immediately issue another request.

> curl -X GET "localhost:8080/hello"
hello2%

As you can see, you can witness the new value being returned immediately – Quarkus’ hot reload kicked in which allows you to stay in the flow while actively developing your application.

Meanwhile in the logs:

2021-08-26 08:35:16,005 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (vert.x-worker-thread-0) Restarting quarkus due to changes in HelloResource.class.
2021-08-26 08:35:16,014 INFO [io.quarkus] (Quarkus Main Thread) quarkus-hello stopped in 0.008s
__ ____ __ _____ ___ __ ____ ______ 
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ 
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 
2021-08-26 08:35:16,286 INFO [io.quarkus] (Quarkus Main Thread) quarkus-hello 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.1.3.Final) started in 0.268s. Listening on: http://localhost:8080
2021-08-26 08:35:16,286 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2021-08-26 08:35:16,287 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy, smallrye-context-propagation]
2021-08-26 08:35:16,288 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (vert.x-worker-thread-0) Live reload total time: 0.326s

However, if you want to ship your application, mvn package is your friend, and then you’re free to distribute a jar however you wish or containerize it.

Just don’t forget that Quarkus stores dependencies in a separate target/quarkus-app/lib directory!

Running a Standalone Jar

  1. mvn package
  2. java -jar target/quarkus-app/quarkus-run.jar

Running a Containerized Jar

  1. mvn package
  2. docker build -f src/main/docker/Dockerfile.jvm -t pivovarit/quarkus-hello .
  3. docker run pivovarit/quarkus-hello

Running a Containerized Native Image

In order to build a native image, you don’t need to have GraalVM configured locally, Quarkus can use a dedicated containerized version of GraalVM for that:

  1. mvn package -Pnative -Dquarkus.native.container-build=true
  2. docker build -f src/main/docker/Dockerfile.native -t pivovarit/quarkus-hello .
  3. docker run pivovarit/quarkus-hello

Enjoy your application starting in just a handful of milliseconds:

__ ____ __ _____ ___ __ ____ ______ 
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ 
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 
2021-08-26 09:24:01,610 INFO [io.quarkus] (main) quarkus-hello 1.0.0-SNAPSHOT native (powered by Quarkus 2.1.3.Final) started in 0.026s. Listening on: http://0.0.0.0:8080
2021-08-26 09:24:01,610 INFO [io.quarkus] (main) Profile prod activated. 
2021-08-26 09:24:01,610 INFO [io.quarkus] (main) Installed features: [cdi, resteasy, smallrye-context-propagation]

Summary

Quarkus is a modern framework that fully embraces other modern technologies like containerization, build-time initialization, and GraalVM, and it’s definitely worth having it on the radar.

You can expect more Quarkus content soon.




If you enjoyed the content, consider supporting the site: