Quarkus: Get started with Kubernetes-native Java – InfoWorld

Matthew Tyson By
Software Architect, InfoWorld |
Quarkus is a full-stack, open-source Java framework launched in 2019 by Red Hat. Quarkus is an alternative to Spring (although it can also be integrated with Spring), with some interesting features all to itself.
Quarkus is designed from the ground up to be “cloud-native,” meaning it’s tuned for Kubernetes, serverless platforms, and a variety of libraries like Apache Kafka (for stream processing) and JAX-RS (for RESTful web services). Quarkus also sports a full CDI (contexts and dependency injection) engine and Reactive programming support.
Read on for a hands-on introduction to Quarkus.
Quarkus supports Maven and Gradle as build tool wrappers, but also ships with a command-line interface (CLI) tool. We’ll begin by installing the CLI via the JBang tool. From the command line, run the code in Listing 1.
Once the command completes, typing quarkus -version should return a result.
Create a new app by typing quarkus create app com.infoworld:my-quarkus:1.0, where com.infoworld is the group ID, my-quarkus is the artifact ID, and 1.0 is the version number.
The command-line tool has many options that you can use to configure things. You can get a look at these options by typing quarkus --help. You can get help with a specific command by typing quarkus create app --help. Notice you can define things like which build tool wrapper to use.
Now move into the new my-quarkus directory and type quarkus dev. Quarkus dev mode represents a neat approach. It supports hot code loading and allows you to run tests at will without stopping your container. This is why you are given some command options after the dev container spins up with the prompt:
This means you can make code changes, including adding tests, and then run the tests with r. You can also change logging levels with h or stop the container with q.
By default, Quarkus dev mode only listens on localhost. If you want to listen on all networks, you can add the host param:
To build the app for production, you use the quarkus build command.
While the app is running in dev mode, visit localhost:8080, and you will see the welcome screen, similar to Figure 1.
Inside the new app directory is the src directory, following the typical Maven layout, with test for tests and main for the app files. Inside /src/main are three directories: /src/main/resources, where your static files live (including the HTML pages that drive your pages like src/main/resources/META-INF/resources/index.html); /src/main/java, where your back-end code and middleware code live; and /src/main/docker, where Quarkus has generated default Dockerfiles for you (including Dockerfile.native for running without a JVM).
Any changes you make to the app will be reflected when the browser is refreshed. For example, you can open the src/main/java/com/infoworld/GreetingResource.java file and see a JAX-RS endpoint. If you modify the message and reload localhost:8080/hello, you’ll find your changes reflected.
Quarkus has many capabilities that are delivered via extensions that can be added with a command. To get a sense of what Quarkus supports, take a look at this Git repo, which contains several dozen examples for using Quarkus with the likes of JPA, Kafka, MongoDB, Amazon S3, and Knative. These examples are also good for using as starting points when developing a Quarkus app with these technologies (hence the name quickstarts).
You can see which extensions are installed in your app by running quarkus ext ls. You’ll see that right now only quarkus-resteasy is installed. You can get a list of available installable modules with quarkus ext ls -i.
Installation is performed with the quarkus ext add command.
Quarkus ships with a custom-built dependency injection engine, called ArC. ArC is a partial implementation of the CDI spec, and also has its own special features. Overall, the ArC system is simpler and easier to understand than CDI.
Let’s see how to add a service class for use by the RESTful resource. Begin by creating a new file at /src/main/java/com/infoworld/service/MyService.java. Add the code seen in Listing 3.
MyService is a very simple class with a single method, getRandom(), which returns a random integer. It is annotated with the CDI standard annotation, @ApplicationScoped, that makes it available to the DI system. (Learn more about CDI scopes and contexts here.) Note that Quarkus CDI is included in your project because the RESTEasy extension uses it.
Now open up the /src/main/java/com/infoworld/GreetingResource.java class and modify it as seen in Listing 4.
The key element here is the @Inject annotation, which causes the CDI engine to fulfill the myService reference with the resource bean we created in Listing 4. This is then used to generate the random number for the /hello path.
Now if you return to the command line where Quarkus dev is running, and type r to rerun tests, you’ll see that the test case for the RESTEasy endpoint fails. Let’s fix that. Open test/java/com/infoworld/GreetingResourceTest.java. Notice this class uses several different testing libraries already helpfully provided by Quarkus, including the RestAssured library, which makes for easy testing of RESTful endpoints.
Modify GreetingResourceTest as seen in Listing 5.
As noted in the comments, only two lines are changed. You simply check for the existence of the word “machine” in the response body. Now if you run the tests with the r command, they will pass.
Let’s go a little deeper and make a call to an external REST API (the Star Wars API, aka SWAPI) in the service class. Begin by adding the quarkus-rest-api client by running quarkus ext add quarkus-rest-client. Note that you can do this in another window while the app is still running and Quarkus will apply the extension. Pretty impressive.
We’ll also leverage the rest-client-jackson extension to make modeling the data simple. Type quarkus ext add rest-client-jackson.
Create a model class in a new directory: src/main/java/com/infoworld/client/Person.java. This will be a very simple data transfer object that Jackson will populate for us, as seen in Listing 6.
Notice we use the @JsonIgnoreProperties so no errors are thrown when fields exist on the source JSON that don’t exist on the model object.
In the same directory, create a new service class that will hit the SWAPI endpoint: /src/main/java/com/infoworld/client/SwapiClient.java. See the contents of that file in Listing 7.
Notice the interface is registered as a rest client with the @RegisterRestClient annotation. The method getById is also annotated to define it as hitting a GET HTTP Method found as "/people/{id}", where the id is going to be provided by the call to the getById(@PathParam Integer id) method. We are here defining with the same annotations that define a restful endpoint, a restful client.
But where is the root of the endpoint defined? Open up src/main/resources/application.properties and add the two lines seen in Listing 8.
More info on these properties and how they are wired into the application is available here.
Now update the GreetingResource to use the new client service, as in Listing 9.
Now we are injecting the rest client into the swapiClient variable, and calling the getById method with a random ID from the random number service you created earlier. Now you’ll get a response from localhost:8080/hello that goes something like this: 
This was a whirlwind tour of some of the power of Quarkus, but only the beginning. Quarkus is definitely a valid alternative to Spring, and continues to see active development, with new and useful features being added frequently. The next time you reach for a Java framework, consider Quarkus.
All of the code for this tutorial is available here.
Matthew Tyson is a founder of Dark Horse Group, Inc. He believes in people-first technology. When not playing guitar, Matt explores the backcountry and the philosophical hinterlands. He has written for JavaWorld since 2007.
Copyright © 2021 IDG Communications, Inc.
Copyright © 2021 IDG Communications, Inc.