We took a look at Quarkus so you don’t have to
By K Clark, Korbinian Martini and Michael Vigerl.
We constantly run into new, shiny, and revolutionary frameworks, especially for JavaScript, online. Life is too short to jump on every framework hype train. Most frameworks disappear as fast as they appear, but some are here to stay… For example, Quarkus, the supersonic subatomic Java framework!
The three of us dedicated a Comsysto lab day to Quarkus, meaning we paused our regular project work for a day to try out new and exciting technologies on company time. We (a.k.a. our older colleagues) started using Spring at version 1.x sometime around 2004. All of us were familiar with (more recent versions of) Spring and wanted to find out what is behind the bold claims Quarkus makes. In the following we will focus on Quarkus’ Live Reload, building native images, and the claim of being reactive at its core. After going over these three claims we will share potential second steps for you to try out and our take on Quarkus.
Workflow with Live Reload and custom Maven goals
One difference to Spring, and a big feature of Quarkus is the developer’s workflow while coding.
When using Spring you cycle from updating code, compiling, running unit tests, starting your application, and trying it out. Quarkus tries to streamline this workflow by partially automating it for you.
The application will start in an interactive CLI with shortcuts for rerunning tests or resetting your app’s state. Restarting this “Dev Mode” should rarely be necessary since Quarkus scans for code changes, compiles them in the background, and silently deploys them to your running application. You can almost instantly look at the new output or UI of your application or start debugging the application in your favorite IDE. While hot swapping is not a new concept, we did not find the typical limitations during our testing, such as only working properly when the public interfaces of your classes remain unchanged.
You can also use the Dev UI deployed alongside your code. It is comparable to the web UI of your favorite application server from ancient times. It allows you to manage caches, DB connections, and other configurations. The Dev UI can be extended by 3rd party libraries and, therefore, has a huge pool of utilities to pick from.
If you used Maven before, you are probably used to running maven clean install
to ensure you have a properly built application. Then you can start and test the application while changing your code. Once you feel like trying it out, restart the cycle. With an initiated Quarkus project maven clean install
will build — just like with Spring — a release version of your code and deploy it to your .m2 directory. It works, but you’re not taking advantage of the aforementioned features of dev mode with this build. Instead, you should hit maven compile quarkus:dev
or quarkus dev
if you have the Quarkus CLI installed to get into “Dev Mode”.
Assuming you have a working build pipeline, this is all you would do on your machine. Once you are happy with your changes, push them to a build server where a native image will be built.
Compilation to machine native images
In a modern, serverless cloud setting, you shouldn’t need to pay for dedicated hardware running 24/7 for you. Instead, your application should start at any point in time and terminate once it’s fulfilled its duties to save resources. This approach to cost-saving adds “a short cold start duration” to the list of requirements.
This is where native images come in. Contrary to using a normal package with the JVM that encompasses many things the application does not need, a native image uses ahead-of-time compilation to prune all code that won’t get called, like dead code or parts of libraries that are not required at runtime. Additionally, it uses a reduced version of the JVM to achieve a fast startup time and reduce resource consumption. What you get is a native executable, a binary that has exactly what it needs to run on your targeted operating system.
Spring also supports building native images with its Spring-native component. However, Quarkus is even smaller and faster. Moreover, Quarkus supports GraalVM, the native image compiler used by Spring, and a downstream distribution called Mandrel, specifically designed to be used with Quarkus promising to make its native images even more optimized.
On Windows, there are some difficulties to overcome, like using the Microsoft Native Tools for Visual Studio and typing the commands there instead of the other command lines. Also, building a native image on Windows without configuration leads to the generation of an .exe-file, which is not going to work on Linux containers or environments.
Fortunately, Quarkus also provides a way to build native images for containerized environments even without having GraalVM or Mandrel installed, which is specifically useful in a CI pipeline.
There is a lot more Quarkus can do with native images, so if you want to check that out go to https://quarkus.io/guides/building-native-image.
Reactive Patterns
The third and final thing that sparked our interest is that “Quarkus is a Reactive Framework”. Unfortunately, Reactive is one of the overused words in our industry, so let’s clarify what it means in our context. Quarkus uses the definition:
Reactive is a set of principles to build robust, efficient, and concurrent applications and systems. These principles let you handle more load than traditional approaches while using the resources (CPU and memory) more efficiently while also reacting to failures gracefully.
So, what’s the difference between reactive and traditional imperative execution models? The short answer is non-blocking I/O threads. When interacting with a remote service, e.g., waiting for an HTTP response, a reactive execution model does not block. Instead, it schedules the I/O operation and attaches a continuation (= a request for processing the remaining code). When the scheduled I/O completes, the I/O thread executes the continuation, and the processing of the pending request continues.
Quarkus proposes two ways of writing continuation-passing code:
- Mutiny, an event-driven reactive programming library.
Mutiny implements Reactive Streams, which is an initiative to provide a standard for asynchronous stream processing with non-blocking back pressure on the JVM (If Mono and Flux sound familiar you have already used this with Spring WebFlux). - Kotlin coroutines (asynchronous code in a sequential manner)
There might be a third option in the future: Project Loom is coming to the JDK soon-ish, and the Quarkus architecture is ready to support it. This project was summarized really well by Baeldung (as always).
As wonderful as this is, there are times when traditional, imperative, blocking code is easier to write or necessary for some other reason. With Quarkus you can choose to write imperative, reactive, and even mix the two, depending on what makes the most sense for your application.
Where to go next
If the aforementioned features sparked your curiosity, and you now want to quickly try it yourself, your best bet is to go over to Get Started — Quarkus. During our Lab, we tried to keep the prerequisites for starting our first Quarkus app as small as possible. Hence, we skipped the installation of the Quarkus CLI. The list of software you will need (and might already have on your laptop):
- Java or Kotlin
- Docker
- Maven
- Some IDE (we used IntelliJ)
Now you have two options: running a maven command or clicking your way through an IntelliJ template. Open your command line and run
maven io.quarkus.platform:quarkus-maven-plugin:2.12.1.Final:create -DprojectGroupId=org.acme -DprojectArtifactId=getting-started -Dextensions=”resteasy-reactive”
to create a scaffold and a few example services. The same outcome can be achieved using IntelliJ by clicking “New Project” and selecting the Quarkus template. The wizard will then ask you about your preferred language, JDK, a build tool, and extensions.
Once this has been completed, you can start your app either with the maven command or via the run button in your IDE. And that’s it! You can now start to replace the example services with your own logic.
Second Steps
Now that you have a basic understanding of Quarkus, and some of its features, and know how to start a basic application, you are ready to dig deeper into what Quarkus can offer. You can look at their persistence library called Panache, where you can apply the repository- or active-record-patterns. Or you could deploy a serverless application with a cloud provider of your choice using a native image, as we did in our project.
To build a native image with Quarkus on your system you need to have GraalVM or Mandrel installed.
The command to build the image in maven is maven package -Dnative
and to test the resulting native image maven verify -Pnative
. Alternatively, you can build a Quarkus native image by running maven package -Dnative -Dquarkus.native.container-build=true
. This requires a working container runtime environment such as Docker.
Quarkus offers a lot of good guides that can help you explore what interests you most.
If you would prefer to watch someone else explore Quarkus, and you are interested in a more in-depth introduction, you can watch this one-hour-long video in German from two of our colleagues.
In our opinion…
With all that said, we would like to encourage you to try Quarkus. Apart from a few hiccups, Quarkus was an easy-to-use framework that convinced us with a lot of features tailored to the current and future technological requirements and demands. There is a high chance Quarkus will make it into Comsysto’s repertoire of recommended technologies.
Even though there are projects (e.g., Red Hat Migration Toolkit) for automating migration from Spring to Quarkus, right now, we would not recommend migrating an existing Spring application to Quarkus, unless there are significant performance issues that might only get solved by migrating to Quarkus. Note that there are still a few frameworks, extensions, and connectors missing or under development.
If you are lucky enough to start on a green field and have high scalability or fast cold start requirements due to using a “serverless” backend, then you should definitely consider Quarkus.
As with any new technology, make sure your developers are on board and as interested in Quarkus as we are.
This blog post is published by Comsysto Reply GmbH.