Posted on Leave a comment

Using Kubernetes ConfigMaps to define your Quarkus application’s properties

So, you wrote your Quarkus application, and now you want to deploy it to a Kubernetes cluster. Good news: Deploying a Quarkus application to a Kubernetes cluster is easy. Before you do this, though, you need to straighten out your application’s properties. After all, your app probably has to connect with a database, call other services, and so on. These settings are already defined in your file, but the values match the ones for your local environment and won’t work once deployed onto your cluster.

So, how do you easily solve this problem? Let’s walk through an example.

Create the example Quarkus application

Instead of using a complex example, let’s take a simple use case that explains the concept well. Start by creating a new Quarkus app:

$ mvn io.quarkus:quarkus-maven-plugin:1.1.1.Final:create

You can keep all of the default values while creating the new application. In this example, the application is named hello-app. Now, open the file and refactor it to look like this:

@Path("/hello") public class HelloResource { @ConfigProperty(name = "greeting.message") String message; @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return "hello " + message; } } 

In your file, now add greeting.message=localhost. The @ConfigProperty annotation is not in the scope of this article, but here we can see how easy it is to inject properties inside our code using this annotation.

Now, let’s start our application to see if it works as expected:

$ mvn compile quarkus:dev

Browse to http://localhost:8080/hello, which should output hello localhost. That’s it for the Quarkus app. It’s ready to go.

Deploy the application to the Kubernetes cluster

The idea here is to deploy this application to our Kubernetes cluster and replace the value of our greeting property with one that will work on the cluster. It is important to know here that all of the properties from are exposed, and thus can be overridden with environment variables. The convention is to convert the name of the property to uppercase and replace every dot (.) with an underscore (_). So, for instance, our greeting.message will become GREETING_MESSAGE.

At this point, we are almost ready to deploy our app to Kubernetes, but we need to do three more things:

  1. Create a Docker image of your application and push it to a repository that your cluster can access.
  2. Define a ConfgMap resource.
  3. Generate the Kubernetes resources for our application.

To create the Docker image, simply execute this command:

$ docker build -f src/main/docker/Dockerfile.jvm -t quarkus/hello-app .

Be sure to set the right Docker username and to also push to an image registry, like docker-hub or quay. If you are not able to push an image, you can use sebi2706/hello-app:latest.

Next, create the file config-hello.yml:

apiVersion: v1 data: greeting: "Kubernetes" kind: ConfigMap metadata: name: hello-config 

Make sure that you are connected to a cluster and apply this file:

$ kubectl apply -f config-hello.yml

Quarkus comes with a useful extension, quarkus-kubernetes, that generates the Kubernetes resources for you. You can even tweak the generated resources by providing extra properties—for more details, check out this guide.

After installing the extension, add these properties to our file so it generates extra configuration arguments for our containers specification: kubernetes.env-vars[0].name=GREETING_MESSAGE kubernetes.env-vars[0].value=greeting kubernetes.env-vars[0].configmap=hello-config

Run mvn package and view the generated resources in target/kubernetes. The interesting part is in spec.containers.env:

- name: "GREETING_MESSAGE"   valueFrom:   configMapKeyRef:     key: "greeting"    name: "hello-config"

Here, we see how to pass an environment variable to our container with a value coming from a ConfigMap. Now, simply apply the resources:

$ kubectl apply -f target/kubernetes/kubernetes.yml

Expose your service:

kubectl expose deployment hello --type=NodePort

Then, browse to the public URL or do a curl. For instance, with Minikube:

$ curl $(minikube service hello-app --url)/hello

This command should output: hello Kubernetes.


Now you know how to use a ConfigMap in combination with environment variables and your Quarkus’s As we said in the introduction, this technique is particularly useful when defining a DB connection’s URL (like QUARKUS_DATASOURCE_URL) or when using the quarkus-rest-client (ORG_SEBI_OTHERSERVICE_MP_REST_URL).


The post Using Kubernetes ConfigMaps to define your Quarkus application’s properties appeared first on Red Hat Developer.

Posted on Leave a comment

How Quarkus brings imperative and reactive programming together

The supersonic subatomic Java singularity has expanded!

42 releases, 8 months of community participation, and 177 amazing contributors led up to the release of Quarkus 1.0.  This release is a significant milestone with a lot of cool features behind it. You can read more in the release announcement.

Building on that awesome news, we want to delve into how Quarkus unifies both imperative and reactive programming models and its reactive core. We’ll start with a brief history and then take a deep dive into what makes up this dual-faceted reactive core and how Java developers can take advantage of it.

Microservices, event-driven architectures, and serverless functions are on the rise. Creating a cloud-native architecture has become more accessible in the recent past; however, challenges remain, especially for Java developers. Serverless functions and microservices need faster startup times, consume less memory, and above all offer developer joy. Java, in that regard, has just in recent years done some improvements (e.g., ergonomics enhancements for containers, etc.). However, to have a performing container-native Java, it hasn’t been easy. Let’s first take a look at some of the inherent issues for developing container-native Java applications.

Let’s start with a bit of history.

Threads CPUs Java and Containers

Threads and containers

As of version 8u131, Java is more container-aware, due to the ergonomics enhancements. So now, the JVM knows the number of cores it’s running on and can customize thread pools accordingly — typically the fork/join pool. That’s all great, but let’s say we have a traditional web application that uses HTTP servlets or similar on Tomcat, Jetty, or the like. In effect, this application gives a thread to each request allowing it to block this thread when waiting for IO to occur, such as accessing databases, files, or other services. The sizing for such an application depends on the number of concurrent requests rather than the number of available cores; this also means quota or limits in Kubernetes on the number of cores will not be of great help and eventually will result in throttling.

Memory exhaustion

Threads also cost memory. Memory constraints inside a container do not necessarily help. Spreading that over multiple applications and threading to a large extent will cause more switching and, in some cases, performance degradation. Also, if an application uses traditional microservices frameworks, creates database connections, uses caching, and perhaps needs some more memory, then straightaway one would also need to look into the JVM memory management so that it’s not getting killed (e.g., XX:+UseCGroupMemoryLimitForHeap). Even though JVM can understand cgroups as of Java 9 and adapt memory accordingly, it can still get quite complex to manage and size the memory.

Quotas and limits

With Java 11, we now have the support for CPU quotas (e.g., PreferContainerQuotaForCPUCount). Kubernetes also provides support for limits and quotas. This could make sense; however, if the application uses more than the quota again, we end up with sizing based on cores, which in the case of traditional Java applications, using one thread per request, is not helpful at all.

Also, if we were to use quotas and limits or the scale-out feature of the underlying Kubernetes platform, the problem wouldn’t solve itself; we would be throwing more capacity at the underlying issue or end up over-committing resources. And if we were running this on a high load in a public cloud, certainly we would end up using more resources than necessary.

What can solve this?

A straightforward solution to these problems would be to use asynchronous and non-blocking IO libraries and frameworks like Netty, Vert.x, or Akka. They are more useful in containers due to their reactive nature. By embracing non-blocking IO, the same thread can handle multiple concurrent requests. While a request processing is waiting for some IO, the thread is released and so can be used to handle another request. When the IO response required by the first request is finally received, processing of the first request can continue. Interleaving request processing using the same thread reduces the number of threads drastically and also resources to handle the load.

With non-blocking IO, the number of cores becomes the essential setting as it defines the number of IO threads you can run in parallel. Used properly, it efficient dispatches the load on the different cores, handling more with fewer resources.

Is that all?

And, there’s more. Reactive programming improves resource usage but does not come for free. It requires that the application code embrace non-blocking and avoid blocking the IO thread. This is a different development and execution model. Although there are many libraries to help you do this, it’s still a mind-shift.

First, you need to learn how to write code executed asynchronously because, as soon as you start using non-blocking IOs, you need to express what is going to happen once the response is received. You cannot wait and block anymore. To do this, you can pass callbacks, use reactive programming, or continuation. But, that’s not all, you need to use non-blocking IOs and so have access to non-blocking servers and clients for everything you need. HTTP is the simple case, but think about database access, file systems, and so on.

Although end-to-end reactive provides the best efficiency, the shift can be hard to comprehend. Having the ability to mix both reactive and imperative code is becoming essential to:

  1. Use efficiently the resources on hot paths, and
  2. Provide a simpler code style for the rest of the application.

Enter Quarkus

This is what Quarkus is all about: unifying reactive and imperative in a single runtime.

Quarkus uses Vert.x and Netty at its core. And, it uses a bunch of reactive frameworks and extensions on top to help developers. Quarkus is not just for HTTP microservices, but also for event-driven architecture. Its reactive nature makes it very efficient when dealing with messages (e.g., Apache Kafka or AMQP).

The secret behind this is to use a single reactive engine for both imperative and reactive code.

Quarkus does this quite brilliantly. Between imperative and reactive, the obvious choice is to have a reactive core. What that helps with is a fast non-blocking code that handles almost everything going via the event-loop thread (IO thread). But, if you were creating a typical REST application or a client-side application, Quarkus also gives you the imperative programming model. For example, Quarkus HTTP support is based on a non-blocking and reactive engine (Eclipse Vert.x and Netty). All the HTTP requests your application receive are handled by event loops (IO Thread) and then are routed towards the code that manages the request. Depending on the destination, it can invoke the code managing the request on a worker thread (servlet, Jax-RS) or use the IO was thread (reactive route).

For messaging connectors, non-blocking clients are used and run on top of the Vert.x engine. So, you can efficiently send, receive, and process messages from various messaging middleware.

To help you get started with reactive on Quarkus, there are some well-articulated guides on

There are also reactive demo scenarios that you can try online; you don’t need a computer or an IDE, just give it a go in your browser. You can try them out here.

Additional resources


The post How Quarkus brings imperative and reactive programming together appeared first on Red Hat Developer.

Posted on Leave a comment

Quarkus: Modernize “helloworld” JBoss EAP quickstart, Part 1

Quarkus is, in its own words, “Supersonic subatomic Java” and a “Kubernetes native Java stack tailored for GraalVM & OpenJDK HotSpot, crafted from the best of breed Java libraries and standards.” For the purpose of illustrating how to modernize an existing Java application to Quarkus, I will use the Red Hat JBoss Enterprise Application Platform (JBoss EAP) quickstarts helloworld quickstart as sample of a Java application builds using technologies (CDI and Servlet 3) supported in Quarkus.

It’s important to note that both Quarkus and JBoss EAP rely on providing developers with tools based—as much as possible—on standards. If your application is not already running on JBoss EAP, there’s no problem. You can migrate it from your current application server to JBoss EAP using the Red Hat Application Migration Toolkit. After that, the final and working modernized version of the code is available in the repository inside the helloworld module.

This article is based on the guides Quarkus provides, mainly Creating Your First Application and Building a Native Executable.

Get the code

To start, clone the JBoss EAP quickstarts repository locally, running:

$ git clone Cloning into 'jboss-eap-quickstarts'... remote: Enumerating objects: 148133, done. remote: Total 148133 (delta 0), reused 0 (delta 0), pack-reused 148133 Receiving objects: 100% (148133/148133), 59.90 MiB | 7.62 MiB/s, done. Resolving deltas: 100% (66476/66476), done. $ cd jboss-eap-quickstarts/helloworld/

Try plain, vanilla helloworld

The name of the quickstart is a strong clue about what this application does, but let’s follow a scientific approach in modernizing this code, so first things first: Try the application as it is.

Deploy helloworld

  1. Open a terminal and navigate to the root of the JBoss EAP directory EAP_HOME (which you can download).
  2. Start the JBoss EAP server with the default profile by typing the following command:
$ EAP_HOME/bin/ 

Note: For Windows, use the EAP_HOME\bin\standalone.bat script.

After a few seconds, the log should look like:

[] (Controller Boot Thread) WFLYSRV0025: JBoss EAP 7.2.0.GA (WildFly Core 6.0.11.Final-redhat-00001) started in 3315ms - Started 306 of 527 services (321 services are lazy, passive or on-demand)
  1. Open in a browser, and a page like Figure 1 should appear:
The JBoss EAP home page.

Figure 1: The JBoss EAP home page.

  1. Following instructions from Build and Deploy the Quickstart, deploy the helloworld quickstart and execute (from the project root directory) the command:
$ mvn clean install wildfly:deploy 

This command should end successfully with a log like this:

[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 8.224 s 

The helloworld application has now been deployed for the first time in JBoss EAP in about eight seconds.

Test helloworld

Following the Access the Application guide, open in the browser and see the application page, as shown in Figure 2:

JBoss EAP's Hello World.

Figure 2: JBoss EAP’s Hello World.

Make changes

Change the createHelloMessage(String name) input parameter from World to Marco (my ego is cheap):

writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");

Execute again the command:

$ mvn clean install wildfly:deploy 

and then refresh the web page in the browser to check the message displayed changes, as shown in Figure 3:

JBoss EAP's Hello Marco.

Figure 3: JBoss EAP’s Hello Marco.

Undeploy helloworld and shut down

If you want to undeploy (optional) the application before shutting down JBoss EAP, run the following command:

$ mvn clean install wildfly:undeploy 

To shut down the JBoss EAP instance, enter Ctrl+C in the terminal where it’s running.

Let’s modernize helloworld

Now we can leave the original helloworld behind and update it.

Create a new branch

Create a new working branch once the quickstart project finishes executing:

$ git checkout -b quarkus 7.2.0.GA 

Change the pom.xml file

The time has come to start changing the application. starting from the pom.xml file. From the helloworld folder, run the following command to let Quarkus add XML blocks:

$ mvn io.quarkus:quarkus-maven-plugin:0.23.2:create 

This article uses the 0.23.2 version. To know which is the latest version is, please refer to, since the Quarkus release cycles are short.

This command changed the pom.xml, file adding:

  • The property <quarkus.version> to define the Quarkus version to be used.
  • The <dependencyManagement> block to import the Quarkus bill of materials (BOM). In this way, there’s no need to add the version to each Quarkus dependency.
  • The quarkus-maven-plugin plugin responsible for packaging the application, and also providing the development mode.
  • The native profile to create application native executables.

Further changes required to pom.xml, to be done manually:

  1. Move the <groupId> tag outside of the <parent> block, and above the <artifactId> tag. Because we remove the <parent> block in the next step, the <groupId> must be preserved.
  2. Remove the <parent> block: The application doesn’t need the JBoss parent pom anymore to run with Quarkus.
  3. Add the <version> tag (below the <artifactId> tag) with the value you prefer.
  4. Remove the <packaging> tag: The application won’t be a WAR anymore, but a plain JAR.
  5. Change the following dependencies:
    1. Replace the javax.enterprise:cdi-api dependency with io.quarkus:quarkus-arc, removing <scope>provided</scope> because—as stated in the documentation—this Quarkus extension provides the CDI dependency injection.
    2. Replace the org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec dependency with io.quarkus:quarkus-undertow, removing the <scope>provided</scope>, because—again as stated in the documentation—this is the Quarkus extension that provides support for servlets.
    3. Remove the org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec dependency because it’s coming with the previously changed dependencies.

The pom.xml file’s fully changed version is available at

Note that the above mvn io.quarkus:quarkus-maven-plugin:0.23.2:create command, besides the changes to the pom.xml file, added components to the project. The added file and folders are:

  • The files mvnw and mvnw.cmd, and .mvn folder: The Maven Wrapper allows you to run Maven projects with a specific version of Maven without requiring that you install that specific Maven version.
  • The docker folder (in src/main/): This folder contains example Dockerfile files for both native and jvm modes (together with a .dockerignore file).
  • The resources folder (in src/main/): This folder contains an empty file and the sample Quarkus landing page index.html (more in the section “Run the modernized helloworld“).

Run helloworld

To test the application, use quarkus:dev, which runs Quarkus in development mode (more details on Development Mode here).

Note: We expect this step to fail as changes are still required to the application, as detailed in this section.

Now run the command to check if and how it works:

$ ./mvnw compile quarkus:dev [INFO] Scanning for projects... [INFO] [INFO] ----------------< org.jboss.eap.quickstarts:helloworld >---------------- [INFO] Building Quickstart: helloworld quarkus [INFO] --------------------------------[ war ]--------------------------------- [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ helloworld --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 2 resources [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ helloworld --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- quarkus-maven-plugin:0.23.2:dev (default-cli) @ helloworld --- Listening for transport dt_socket at address: 5005 INFO [io.qua.dep.QuarkusAugmentor] Beginning quarkus augmentation INFO [org.jbo.threads] JBoss Threads version 3.0.0.Final ERROR [] Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors [error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type and qualifiers [@Default] - java member: - declared on CLASS bean [types=[javax.servlet.ServletConfig,,, javax.servlet.GenericServlet, javax.servlet.Servlet, java.lang.Object, javax.servlet.http.HttpServlet], qualifiers=[@Default, @Any],] at io.quarkus.arc.processor.BeanDeployment.processErrors( at io.quarkus.arc.processor.BeanDeployment.init( at io.quarkus.arc.processor.BeanProcessor.initialize( at io.quarkus.arc.deployment.ArcProcessor.validate( at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke( at sun.reflect.DelegatingMethodAccessorImpl.invoke( at java.lang.reflect.Method.invoke( at io.quarkus.deployment.ExtensionLoader$1.execute( at at at org.jboss.threads.EnhancedQueueExecutor.safeRun( at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask( at org.jboss.threads.EnhancedQueueExecutor$ at at Caused by: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type and qualifiers [@Default] - java member: - declared on CLASS bean [types=[javax.servlet.ServletConfig,,, javax.servlet.GenericServlet, javax.servlet.Servlet, java.lang.Object, javax.servlet.http.HttpServlet], qualifiers=[@Default, @Any],] at io.quarkus.arc.processor.Beans.resolveInjectionPoint( at io.quarkus.arc.processor.BeanInfo.init( at io.quarkus.arc.processor.BeanDeployment.init( ... 14 more 

It failed. Why? What happened?

The UnsatisfiedResolutionException exception refers to the HelloService class, which is a member of the HelloWorldServlet class (java member: The problem is that HelloWorldServlet needs an injected instance of HelloService, but it can not be found (even if the two classes are in the very same package).

It’s time to return to Quarkus guides to leverage the documentation and understand how @Inject—and hence Contexts and Dependency Injection (CDI)—works in Quarkus, thanks to the Contexts and Dependency Injection guide. In the Bean Discovery paragraph, it says, “Bean classes that don’t have a bean defining annotation are not discovered.”

Looking at the HelloService class, it’s clear there’s no bean defining annotation, and one has to be added to have Quarkus to discover the bean. So, because it’s a stateless object, it’s safe to add the @ApplicationScoped annotation:

@ApplicationScoped public class HelloService { 

Note: The IDE should prompt you to add the required package shown here (add it manually if need be):

import javax.enterprise.context.ApplicationScoped; 

If you’re in doubt about which scope to apply when the original bean has no scope defined, please refer to the JSR 365: Contexts and Dependency Injection for Java 2.0—Default scope documentation.

Now, try again to run the application, executing again the ./mvnw compile quarkus:dev command:

$ ./mvnw compile quarkus:dev [INFO] Scanning for projects... [INFO] [INFO] ----------------< org.jboss.eap.quickstarts:helloworld >---------------- [INFO] Building Quickstart: helloworld quarkus [INFO] --------------------------------[ war ]--------------------------------- [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ helloworld --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 2 resources [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ helloworld --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 2 source files to /home/mrizzi/git/forked/jboss-eap-quickstarts/helloworld/target/classes [INFO] [INFO] --- quarkus-maven-plugin:0.23.2:dev (default-cli) @ helloworld --- Listening for transport dt_socket at address: 5005 INFO [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation INFO [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 576ms INFO [io.quarkus] (main) Quarkus 0.23.2 started in 1.083s. Listening on: INFO [io.quarkus] (main) Profile dev activated. Live Coding activated. INFO [io.quarkus] (main) Installed features: [cdi] 

This time the application runs successfully.

Run the modernized helloworld

As the terminal log suggests, open a browser to default Quarkus landing page), and the page shown in Figure 4 appears:

The Quarkus dev landing page.

Figure 4: The Quarkus dev landing page.

This application has the following context’s definition in the WebServlet annotation:

@WebServlet("/HelloWorld") public class HelloWorldServlet extends HttpServlet { 

Hence, you can browse to reach the page shown in Figure 5:

The Quarkus dev Hello World page.

Figure 5: The Quarkus dev Hello World page.

It works!

Make changes

Please, pay attention to the fact that the ./mvnw compile quarkus:dev command is still running, and we’re not going to stop it. Now, try to apply the same—very trivial—change to the code and see how Quarkus improves the developer experience:

writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");

Save the file, and then refresh the web page to check that Hello Marco appears, as shown in Figure 6:

The Quarkus dev Hello Marco page.

Figure 6: The Quarkus dev Hello Marco page.

Take time to check the terminal output:

INFO [] (vert.x-worker-thread-3) Changed source files detected, recompiling [/home/mrizzi/git/forked/jboss-eap-quickstarts/helloworld/src/main/java/org/jboss/as/quickstarts/helloworld/] INFO [io.quarkus] (vert.x-worker-thread-3) Quarkus stopped in 0.003s INFO [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) Beginning quarkus augmentation INFO [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) Quarkus augmentation completed in 232ms INFO [io.quarkus] (vert.x-worker-thread-3) Quarkus 0.23.2 started in 0.257s. Listening on: INFO [io.quarkus] (vert.x-worker-thread-3) Profile dev activated. Live Coding activated. INFO [io.quarkus] (vert.x-worker-thread-3) Installed features: [cdi] INFO [] (vert.x-worker-thread-3) Hot replace total time: 0.371s 

Refreshing the page triggered the source code change detection and the Quarkus automagic “stop-and-start.” All of this executed in just 0.371 seconds (that’s part of the Quarkus “Supersonic Subatomic Java” experience).

Build the helloworld packaged JAR

Now that the code works as expected, it can be packaged using the command:

$ ./mvnw clean package

This command creates two JARs in the /target folder. The first is helloworld-<version>.jar, which is the standard artifact built from the Maven command with the project’s classes and resources. The second is helloworld-<version>-runner.jar, which is an executable JAR.

Please pay attention to the fact that this is not an uber-jar, because all of the dependencies are copied into the /target/lib folder (and not bundled within the JAR). Hence, to run this JAR in another location or host, both the JAR file and the libraries in the /lib folder have to be copied, considering that the Class-Path entry of the MANIFEST.MF file in the JAR explicitly lists the JARs from the lib folder.

To create an uber-jar application, please refer to the Uber-Jar Creation Quarkus guide.

Run the helloworld packaged JAR

Now, the packaged JAR can be executed using the standard java command:

$ java -jar ./target/helloworld-<version>-runner.jar INFO [io.quarkus] (main) Quarkus 0.23.2 started in 0.673s. Listening on: INFO [io.quarkus] (main) Profile prod activated. INFO [io.quarkus] (main) Installed features: [cdi] 

As done above, open the URL in a browser, and test that everything works.

Build the helloworld quickstart-native executable

So far so good. The helloworld quickstart ran as a standalone Java application using Quarkus dependencies, but more can be achieved by adding a further step to the modernization path: Build a native executable.

Install GraalVM

First of all, the tools for creating the native executable have to be installed:

  1. Download GraalVM from
  2. Untar the file using the command:

$ tar xvzf graalvm-ce-linux-amd64-

  1. Go to the untar folder.
  2. Execute the following to download and add the native image component:

$ ./bin/gu install native-image

  1. Set the GRAALVM_HOME environment variable to the folder created in step two, for example:

$ export GRAALVM_HOME={untar-folder}/graalvm-ce-

More details and install instructions for other operating systems are available in Building a Native Executable—Prerequisites Quarkus guide.

Build the helloworld native executable

As stated in the Building a Native Executable—Producing a native executable Quarkus guide, “Let’s now produce a native executable for our application. It improves the startup time of the application and produces a minimal disk footprint. The executable would have everything to run the application including the ‘JVM’ (shrunk to be just enough to run the application), and the application.”

To create the native executable, the Maven native profile has to be enabled by executing:

$ ./mvnw package -Pnative

The build took me about 1:10 minutes and the result is the helloworld-<version>-runner file in the /target folder.

Run the helloworld native executable

The /target/helloworld-<version>-runner file created in the previous step. It’s executable, so running it is easy:

$ ./target/helloworld-<version>-runner INFO [io.quarkus] (main) Quarkus 0.23.2 started in 0.006s. Listening on: INFO [io.quarkus] (main) Profile prod activated. INFO [io.quarkus] (main) Installed features: [cdi] 

As done before, open the URL in a browser and test that everything is working.

Next steps

I believe that this modernization, even of a basic application, is the right way to approach a brownfield application using technologies available in Quarkus. This way, you can start facing the issues and tackling them to understand and learn how to solve them.

In part two of this series, I’ll look at how to capture memory consumption data in order to evaluate performance improvements, which is a fundamental part of the modernization process.


The post Quarkus: Modernize “helloworld” JBoss EAP quickstart, Part 1 appeared first on Red Hat Developer.

Posted on Leave a comment

Bring joy to development with Quarkus, the cloud-native Java framework

Our first DevNation Live regional event was held in Bengaluru, India in July. This free technology event focused on open source innovations, with sessions presented by elite Red Hat technologists.

Quarkus is revolutionizing the way that we develop Java applications for the cloud-native era, and in this presentation, Edson Yanaga explains why it also sparks joy.

Watch this live coding session to get familiar with Quarkus and learn how your old and new favorite APIs will start in a matter of milliseconds and consume tiny amounts of memory. Hot reload capabilities for development will bring you instant joy.

Watch the complete presentation:

See the slides here.

Learn more

Join us at an upcoming developer event, and see our collection of past DevNation Live tech talks.


The post Bring joy to development with Quarkus, the cloud-native Java framework appeared first on Red Hat Developer.