In this blog post, I’ll show you how to manually deploy a simple Quarkus application to Azure using Terraform, thanks to NubesGen.
What’s Covered in This Blog Post?
To break it into more details, these are the topics that will be covered in this blog post:
- What is Terraform?
- What is NubesGen?
- Generate a basic Quarkus REST endpoint.
- Package the Quarkus application in an Uber-JAR.
- Use NubesGen to generate Terraform configuration files for a simple Quarkus application.
- Use the Azure Maven plugin to manually deploy the Quarkus application to Azure.
- Check the deployed application on Azure thanks to the web console and the Azure CLI.
Use Case
The goal of this blog post is to focus on Terraform, Azure and NubesGen. So the idea is to use Quarkus to develop a very simple REST endpoint that says hello (yet another hello world). Then we will package this REST endpoint into an Uber-JAR and deploy it on Azure thanks to Terraform and the Azure Maven plugin.

Prerequisites
To code along and be able to execute the code samples, you will need the following tools installed on your machine:
- An IDE, JDK 11 and Maven (Quarkus also supports Gradle if you prefer)
- Azure CLI (
brew install azure-cli
to install on Mac) - Terraform CLI (
brew install hashicorp/tap/terraform
on Mac) - Have an Azure subscription
- cURL
What Is Terraform?
But before we start coding, let me introduce Terraform. Terraform is an open-source tool written in GO for provisioning and managing infrastructures. This can be done on different cloud providers but also on-premise.
As stated on their website, Terraform is an Infrastructure as Code (IaC) tool to “build, change, version and destroy infrastructure safely and efficiently”. The idea is to define, with code, what your infrastructure looks like, and let Terraform provision automatically this infrastructure for you. In a Terraform file, you describe your overall topology (network, security group roles, virtual machines, load balancers, etc) and leave Terraform to create it. If the topology of your application changes over time (eg. you add firewalls, DNS, CDN, etc.), Terraform calculates the delta and only creates/destroys/updates what has changed.
These Terraform files are written in HashiCorp Configuration Language, or HCL, which is human readable and looks like a mixture of JSON and YAML (but it can also be expressed in pure JSON). The advantage of declaring your infrastructure with code is that you can easily read it, change it, store it within your application code, version it, etc.
Terraform Workflow
To be able to provision your infrastructure, Terraform goes through a specific workflow:

The different steps of the workflow are:
- Init: Initializes the code and downloads the requirements mentioned in the configuration files (eg. the Azure provider).
- Plan: Reviews the changes between the deployed infrastructure and what will be deployed. Basically, Terraform checks with the Cloud provider what’s running at the moment, so it gets an up-to-date view of what the infrastructure looks like. Then it figures out what it needs to do, reconciling what’s actually running, with what we want to be running (the desired state).
- Apply: Applies the changes against the real infrastructure to go from what’s running to the desired state.
- Destroy: Destroys the infrastructure.
Terraform Architecture
One of the strengths of Terraform is its ecosystem. Basically, you can create any kind of resource on most of the Cloud providers or on-premise. Why? Because Terraform uses an extension mechanism where providers can build their extension (eg. the Azure provider allows you to create several Azure resources).

The Terraform architecture is made of a core and several providers:
- Core: The core is the one dealing with the workflow lifecycle that we just saw. It takes the configuration files, calculates what’s need to be created/updated/destroyed… and then delegates the tasks to providers.
- Set of providers: There are many providers: IaaS (this can be cloud providers such as AWS, Azure, GCP or on-premise such as Open Stack, VM Ware), PaaS (Heroku, Kubernetes, etc.), to SaaS (DataDog, Fastly, Github Teams, etc.)
Terraform and Azure
Terraform can provision an infrastructure across multiple cloud providers. It’s just a matter for this cloud provider to provide the right Terraform modules. Below is a Terraform configuration file declaring the Azure provider (azurerm
):
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 2.56"
}
}
}
provider "azurerm" {
features {}
}
What Is NubesGen?
There are several ways to manually deploy a Java application to Azure. You can use the Azure command line, the Azure admin console or the Maven Azure plugin. But you need to create the infrastructure first (security roles, storage, configure the DNS, etc.). That’s when Terraform can be handy.
But depending on the complexity of your infrastructure, writing Terraform configuration files can be tricky. That’s when NubesGen becomes very handy: we can use NubesGen to generate the Terraform files for us.
NubesGen is an open-source project that was initiated in 2021. It lets you generate Terraform configuration files (and maybe Pulumi and Bicep in the future) for Azure (and who knows, maybe for other Cloud providers in the future). These configuration files can either be generated using the NubesGen web interface or a cURL command.
To see NubesGen in action, let’s bootstrap a simple Quarkus application and generate some Terraform configuration files.
Generating a Simple Quarkus Application
First of all, let’s generate a simple Quarkus application. To keep it simple, we will bootstrap an application that exposes a REST endpoint that returns “Hello NubesGen with Terraform”. Nothing too fancy, but this allows us to focus on the deployment, not the business code.
Bootstrapping a Quarkus Application
To easily bootstrap a Quarkus application you can either go to code.quarkus.io or use the following Maven command:
$ mvn -U io.quarkus:quarkus-maven-plugin:create \
-DprojectGroupId=org.agoncal.article \
-DprojectArtifactId=quarkus-nubesgen-terraform \
-DpackageName="org.agoncal.article.nubesgen.terraform" \
-Dextensions="quarkus-resteasy"
This creates a Maven structure with all the needed Quarkus configuration as well as some generated business code. In fact, once generated, the entire project is all setup and ready to run and be tested. You can use the following commands to execute Quarkus, test the application and invoke the REST endpoint:
$ mvn quarkus:dev
$ mvn test
$ curl http://localhost:8080/hello
Updating the Generated Code
Let’s change the generated code so our REST endpoint returns Hello NubesGen with Terraform with a timestamp:
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello NubesGen with Terraform " + Instant.now();
}
}
And if we want the tests to pass, it’s just a matter of changing the RESTAssured test:
@QuarkusTest
public class GreetingResourceTest {
@Test
public void testHelloEndpoint() {
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(startsWith("Hello NubesGen"));
}
}
That’s enough business code, time to package and deploy the application.
Packaging the Application
Quarkus has different ways of packaging an application: as a Docker image, a native binary (thanks to GraalVM) or as an executable JAR. In fact, it also allows you to choose between several JAR formats, but that’s another topic. Let’s package the application in an executable Uber-JAR. It’s simple to deploy and portable. To build the Uber-JAR, execute the following command:
$ mvn package -Dquarkus.package.type=uber-jar
As an alternative, you can also set the property in the application.properties
(quarkus.package.type=uber-jar
) so you don’t have to pass it to the command line and just execute mvn package
.
In the target
directory, you end up with two JAR files. The .jar.original
file is the one that is automatically packaged by Maven and is not executable (it’s just a JAR file with our code). The other one (-runner.jar
) is 12 MB and is executable. That’s the one we want to deploy.
$ ll target/
-rw-r--r-- 12M quarkus-nubesgen-terraform-1.0.0-SNAPSHOT-runner.jar
-rw-r--r-- 6.3K quarkus-nubesgen-terraform-1.0.0-SNAPSHOT.jar.original
Executing the Packaged Application
Now that we have built the executable JAR, running the application is just a matter of executing:
$ java -jar target/quarkus-nubesgen-terraform-1.0.0-SNAPSHOT-runner.jar
Once Quarkus is up and running, execute the following cURL command, you should see our Hello NubesGen with Terraform:
$ curl http://localhost:8080/hello
Hello NubesGen with Terraform 2021-07-07T14:21:54.314396Z
Generating the Terraform Configuration Files with NubesGen
We have a simple application, with no database, no authentication, nothing, packaged in an executable Uber-JAR. Let’s ask NubesGen to generate the Terraform configuration files so we can create the needed Azure infrastructure. For that, we can either use the NubesGen website or a cURL command.
Generating with the Website
If you decide to generate the Terraform configuration files from the NubesGen website, you need to manually pick up what you need for your infrastructure. In our case, you need to give a name to the project (eg. quarkus-nubesgen-terraform
), pick up a region and choose Quarkus from the combo box. Then you can specify if the application needs a relational database, a Redis cache or a MongoDB. In our case, we don’t need anything, just leave the checkboxes unchecked.
Click on Download configuration files, this will download a zip file containing the generated Terraform files that you can add at the root of your project.

Generating with a cURL Command
If like me, you prefer the command line, NubesGen allows you to download these configuration files through a cURL command. If you click on or copy cURL script you will get the following cURL command:
$ curl "https://nubesgen.com/quarkus-nubesgen-terraform.tgz?iactool=TERRAFORM®ion=northeurope&application=APP_SERVICE.free&runtime=QUARKUS&database=NONE.free" | tar -xzvf -
This command has the same parameters as the website. The first parameter is the project name (here quarkus-nubesgen-terraform
), then, the region you want to deploy to (here Northern Europe), the Azure plan (Free), the runtime (in our case Quarkus), and we have no database.
Execute this command at the root of your project, you will get a set of generated files.
Generated Files
At the root of our Quarkus project, NubesGens has generated a set of Terraform files under a directory called terraform
. Under this directory, despite the README.md
and .gitignore
files, all the files have the suffix tf
for Terraform. The files are:
main.tf
: Contains the main set of configurations for a module.variables.tf
: Contains the variable definitions for a module.outputs.tf
: Contains the output definitions for a module.
These files can be found at the root of the terraform
directory, but also under the modules/app-service
directory:

Basically, at the root of the terraform
directory the files are used to define the needed providers (Azure in our case) and aggregate the other Terraform files. Under the subdirectory modules
, you will find all the needed modules of our infrastructure (application, databases, etc.). In our case, we only have a Quarkus application, so it is configured under the app-service
directory.
Root Terraform Files
At the root, the main.tf
file starts by declaring the Azure provider. That’s important as we need Terraform to create our infrastructure on Azure:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 2.56"
}
}
}
provider "azurerm" {
features {}
}
Then, the main.tf
file aggregates all the other modules. In our case, we only have an application, that’s why main.tf
only includes the modules under ./modules/app-service
:
module "application" {
source = "./modules/app-service"
resource_group = azurerm_resource_group.main.name
application_name = local.application_name
environment = local.environment
location = var.location
}
The variables.tf
file defines the variables needed for our infrastructure. Here we define the name of our Quarkus application quarkus-nubesgen-terraform
:
variable "application_name" {
type = string
description = "The name of your application"
default = "quarkus-nubesgen-terraform"
}
Application Terraform Files
Under the modules
directory, there is another sub-directory called app-service
. That’s where we have the configuration for the Quarkus application per se. For example, this file sets HTTPs, the version of Java (here, 11), or the listening port for Quarkus:
resource "azurerm_app_service" "application" {
name = "app-${var.application_name}-001"
resource_group_name = var.resource_group
location = var.location
app_service_plan_id = azurerm_app_service_plan.application.id
https_only = true
tags = {
"environment" = var.environment
}
site_config {
linux_fx_version = "JAVA|11-java11"
always_on = false
use_32_bit_worker_process = true
ftps_state = "FtpsOnly"
}
app_settings = {
"WEBSITES_ENABLE_APP_SERVICE_STORAGE" = "false"
# These are app specific environment variables
"QUARKUS_HTTP_PORT" = 80
"QUARKUS_PROFILE" = "prod"
}
}
Executing the Terraform Configuration Files
Thanks to NubesGen we have all the needed Terraform files to configure our infrastructure to run our REST endpoint. Time to execute Terraform. There are several ways of doing, but I’ll be using the Terraform CLI and going step-by-step so you understand what’s happening behind the scene.
Initialising the Configuration
First, let’s initialise the Terraform configuration files. For that, you need to be at the root of the terraform
directory and execute terraform init
:
terraform$ terraform init
Initializing modules...
- application in modules/app-service
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/azurerm versions matching ">= 2.56.0"...
- Installing hashicorp/azurerm v2.66.0...
- Installed hashicorp/azurerm v2.66.0 (signed by HashiCorp)
Terraform has been successfully initialized!
During the initialisation phase, Terraform creates a .terraform
directory with generated files, such as the modules.json
or .terraform.lock.hcl
files. But it also downloads the GO executables needed by the configuration (here the terraform-provider-azurerm_v2.66.0_x5
executable):

You can also check if the configuration is valid with the validate
command and show the state of the execution plan with the show
command:
terraform$ terraform validate
Success! The configuration is valid.
terraform$ terraform show
No state.
If you have GraphViz installed, you can even generate a visual representation of the execution plan with the graph command:
terraform$ terraform graph
terraform$ terraform graph | dot -Tpng > graph.png
The visual aspect looks like this:

Logging in to Azure
If at that moment, you are not logged in to Azure and want to define the plan (with terraform plan
), you will get the following error:
terraform$ terraform plan
│ Error: Error building AzureRM Client: obtain subscription() from Azure CLI: Error parsing json result from the Azure CLI: Error waiting for the Azure CLI: exit status 1: ERROR: Please run 'az login' to set up account.
That’s because you need to be logged in to Azure. You can easily log in with the following Azure CLI command:
terraform$ az login
You have logged in.
terraform$ az account show
{
"environmentName": "AzureCloud",
"homeTenantId": "1234-abcd",
"id": "abcd-1234",
"isDefault": true,
"managedByTenants": [],
"state": "Enabled",
"tenantId": "1234-abcd",
"user": {
"name": "my.email@gmail.com",
"type": "user"
}
}
Planning the Execution
Time to plan the execution. The plan
command shows the changes required by the current configuration. The execution plan is not executed yet, this command just shows what will be executed if you decide to execute the plan:
terraform$ terraform plan
Terraform will perform the following actions:
# azurerm_resource_group.main will be created
# module.application.azurerm_app_service.application will be created
# module.application.azurerm_app_service_plan.application will be created
Plan: 3 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ application_hostname = (known after apply)
+ resource_group = "rg-quarkus-nubesgen-terraform-001"
The logs show that, from what’s currently deployed (nothing yet in our case) and what we’ve defined in the Terraform files, three changes will be made:
- Create an Azure main group,
- create the application service,
- create the plan for the application.
Time to execute this plan!
Applying the Execution Plan
If we agree with the changes that are ready to be made (shown by the plan
command), we need to apply them with the apply
command. This command takes a bit of time because it needs to communicate with Azure to create the needed resources:
terraform$ terraform apply
azurerm_resource_group.main: Creating...
azurerm_resource_group.main: Creation complete after 0s [id=/subscriptions/1234-abcd/resourceGroups/rg-quarkus-nubesgen-terraform-001]
module.application.azurerm_app_service_plan.application: Creating...
module.application.azurerm_app_service_plan.application: Creation complete after 19s [id=/subscriptions/1234-abcd/resourceGroups/rg-quarkus-nubesgen-terraform-001/providers/Microsoft.Web/serverfarms/plan-quarkus-nubesgen-terraform-001] module.application.azurerm_app_service.application: Creating...
module.application.azurerm_app_service.application: Creation complete after 30s [id=/subscriptions/1234-abcd/resourceGroups/rg-quarkus-nubesgen-terraform-001/providers/Microsoft.Web/sites/app-quarkus-nubesgen-terraform-001]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
Outputs:
application_hostname = "https://app-quarkus-nubesgen-terraform-001.azurewebsites.net"
resource_group = "rg-quarkus-nubesgen-terraform-001"
As you can see, the method apply
displays two very important pieces of information: the URL of where we can target our application and the Azure resource group. More on that below.
After running apply
, you can execute terraform show
and it will display the execution plan. On the other hand, if Terraform finds out that the infrastructure is already created and does not need to be updated, you will get a message such as:
terraform$ terraform apply
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
application_hostname = "https://app-quarkus-nubesgen-terraform-001.azurewebsites.net"
resource_group = "rg-quarkus-nubesgen-terraform-001"
Cool! Let’s open our browser and point to our URL:
$ open https://app-quarkus-nubesgen-terraform-001.azurewebsites.net
This is disappointing! No Hello NubesGen with Terraform displayed but instead a web page telling us that the application service is up and running. Yes, but without our application. Well, that’s because we need to deploy our Uber JAR!

Manually Deploying the Application
Thanks to the Terraform configuration files, we have our infrastructure ready to host our Quarkus application. We just need to deploy it. In fact there are several ways to deploy our Uber-JAR. But let’s use the Azure Maven plugin to manually deploy it.
Configuring the Azure Maven Plugin
There is a very convenient way to configure the Azure Maven plugin, and that’s by invoking the config
goal. When you do so, the plugin asks you a set of questions:
$ mvn com.microsoft.azure:azure-webapp-maven-plugin:2.0.0:config
Auth type: AZURE_CLI
Default subscription: (1234-abcd)
Username: my.email@gmail.com
Java SE Web Apps in subscription:
* 1: <create>
2: app-quarkus-nubesgen-terraform-001 (Linux|Java 11|Java SE)
Please confirm webapp properties
Subscription Id : 1234-abcd
AppName : app-quarkus-nubesgen-terraform-001
ResourceGroup : rg-quarkus-nubesgen-terraform-001
Region : northeurope
PricingTier : F1
OS : Linux
Java : Java 11
Web server stack: Java SE
Deploy to slot : false
Confirm (Y/N) [Y]:
Once these questions answered, your pom.xml
is automatically configured with plenty of information. As a matter of fact, we don’t need to have all the configuration set in the pom.xml
as our infrastructure is already defined in the Terraform configuration files. Just the subscriptionId
, resourceGroup
and appName
would do:
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-webapp-maven-plugin</artifactId>
<version>2.0.0</version>
<configuration>
<schemaVersion>v2</schemaVersion>
<subscriptionId>1234-abcd</subscriptionId>
<resourceGroup>rg-quarkus-nubesgen-terraform-001</resourceGroup>
<appName>app-quarkus-nubesgen-terraform-001</appName>
<deployment>
<resources>
<resource>
<directory>${project.basedir}/target</directory>
<includes>
<include>*.jar</include>
</includes>
</resource>
</resources>
</deployment>
</configuration>
</plugin>
Deploying the Uber-JAR with the Azure Maven Plugin
Now, it’s just a matter of using the plugin to deploy our Uber-JAR. For that, we invoke the deploy
goal:
$ mvn azure-webapp:deploy
Auth type: AZURE_CLI
Default subscription: (1234-abcd)
Username: my.email@gmail.com
[INFO] Updating target Web App app-quarkus-nubesgen-terraform-001...
[INFO] Successfully updated Web App app-quarkus-nubesgen-terraform-001.
[INFO] Trying to deploy artifact to app-quarkus-nubesgen-terraform-001...
[INFO] Deploying (target/quarkus-nubesgen-terraform-1.0.0-SNAPSHOT-runner.jar)[jar] ...
[INFO] Successfully deployed the artifact to https://app-quarkus-nubesgen-terraform-001.azurewebsites.net
That’s it! It looks like the application is deployed, let’s check that out.
Checking the Deployed Application on Azure
First of all, we need to check if our REST endpoint is responding. For that, we use the URL that was displayed once the plan executed, and add our hello
path:
$ curl https://app-quarkus-nubesgen-terraform-001.azurewebsites.net/hello
Good! The REST endpoint replies Hello NubesGen with Terraform, so it’s up and running. Let’s check the Azure console.
Checking the Azure Console
If you want to have a look at what’s deployed, one way is to go to the Azure portal. For that, go to https://portal.azure.com and check the resources. You should see the application as well as the plan:

Checking with the Azure CLI
You can also use the Azure CLI. There are several commands you could use, but the webapp list
is the one with the most information:
$ az webapp list -g rg-quarkus-nubesgen-terraform-001
$ az webapp list -g rg-quarkus-nubesgen-terraform-001 --output table
Evolving the Application
The infrastructure is set up and the application is deployed. But as you know, things evolved. If in the future the application needs a database, then you need to update your infrastructure. For that, you change the Terraform configuration files, apply these changes on Azure, and redeploy your application. If the infrastructure does not change, well, you just need to redeploy the application, and that’s it.
Redeploying a New Version of the Application
Now that the Azure Maven plugin is configured, to redeploy a new version of the application is quite easy: you change the code of the REST endpoint, compile it, rebuild a new Uber-JAR and redeploy it:
$ mvn package -Dquarkus.package.type=uber-jar
$ mvn azure-webapp:deploy
$ curl https://app-quarkus-nubesgen-terraform-001.azurewebsites.net/hello
Destroying the Infrastructure
And if one day you need to get rid of the entire infrastructure, Terraform is here to help. A simple destroy
command will go through all the resources it needs to destroy and remove them one by one:
terraform$ terraform destroy
Terraform will perform the following actions:
# azurerm_resource_group.main will be destroyed
# module.application.azurerm_app_service.application will be destroyed
# module.application.azurerm_app_service_plan.application will be destroyed
Plan: 0 to add, 0 to change, 3 to destroy.
Changes to Outputs:
- application_hostname = "https://app-quarkus-nubesgen-terraform-001.azurewebsites.net" -> null
- resource_group = "rg-quarkus-nubesgen-terraform-001" -> null
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value:
module.application.azurerm_app_service.application: Destroying... [id=/subscriptions/1234-abcd/resourceGroups/rg-quarkus-nubesgen-terraform-001/providers/Microsoft.Web/sites/app-quarkus-nubesgen-terraform-001]
module.application.azurerm_app_service_plan.application: Destroying... [id=/subscriptions/1234-abcd/resourceGroups/rg-quarkus-nubesgen-terraform-001/providers/Microsoft.Web/serverfarms/plan-quarkus-nubesgen-terraform-001]
azurerm_resource_group.main: Destroying... [id=/subscriptions/1234-abcd/resourceGroups/rg-quarkus-nubesgen-terraform-001]
azurerm_resource_group.main: Destruction complete after 46s
Destroy complete! Resources: 3 destroyed.
At that moment, a terraform show
command will show… nothing. You can use the Azure CLI to check if the resource group has been deleted:
$ az webapp list -g rg-quarkus-nubesgen-terraform-001
(ResourceGroupNotFound) Resource group 'rg-quarkus-nubesgen-terraform-001' could not be found.
Conclusion
Today Infrastructure as Code is more and more used in projects. It is a nice way to define our infrastructure with code, and Terraform is a major player in this area. But Terraform can be tricky. Its language syntax is simple, but its ecosystem is huge and you need to know all the modules and parameters to configure your infrastructure. Deploying to the cloud, even a simple Java application, can take you a few lines of configuration to write. Writing configuration files is error-prone, and the feedback loop takes time: you change the configuration file, applies it, wait for it to be applied, realize that there is a mistake, change the file, apply it…That’s when NubesGen helps you.
NubesGen is just a generator of Terraform configuration files (Pulumi and Bicep are planned to be supported). The project is young but evolving at a rapid pace. It allows you to configure the infrastructure for a Quarkus application, as well as a Spring application, a simple Java application, packaged as a Docker image or not. You can generate configuration files for simple uses cases (as we just did), but also for more complex ones such as using a relational database, a MongoDB or a Redis cache. And by the way, once you have generated your configuration files, you commit them with your code and change them as you want. NubesGen is just there to generate the files, then, they belong to your project and you make them evolve.
If you plan to deploy your Java application to Azure, you should definitely give NubesGen a try!
By the way. I don’t know about you, but instead of deploying the application with the Azure Maven plugin, I would love to a CI/CD environment that would build my Quarkus application and deploy it automatically to Azure when I commit a new version of the code. Using GitHub Actions maybe. What do you think? But again, that’s GitHub Actions configuration files to be created and I don’t know how to do it. Wait, maybe NubesGen can help? Time for another article…
References
- Introduction to Terraform
- Introduction to HashiCorp Terraform with Armon Dadgar
- Terraform Beginner’s Guide: Everything You Should Know
- Terraform with Azure
- Terraform Provider for Azure (Resource Manager) on GitHub
- Deploy a Quarkus Web App to Azure App Service with Maven
- NubesGen and the NubesGen GitHub repository
You can also get my books and on-line courses on Quarkus.
