Full Stack Quarkus and React

By Marc Nuri San Felix
    What do you get with a Packt Subscription?

  • Instant access to this title and 7,500+ eBooks & Videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Free Chapter
    Chapter 1: Bootstrapping the Project
About this book
React has established itself as one of the most popular and widely adopted frameworks thanks to its simple yet scalable app development abilities. Quarkus comes across as a fantastic alternative for backend development by boosting developer productivity with features such as pre-built integrations, application services, and more that bring a new, revolutionary developer experience to Java. To make the best use of both, this hands-on guide will help you get started with Quarkus and React to create and deploy an end-to-end web application. This book is divided into three parts. In the first part, you’ll begin with an introduction to Quarkus and its features, learning how to bootstrap a Quarkus project from the ground up to create a tested and secure HTTP server for your backend. The second part focuses on the frontend, showing you how to create a React project from scratch to build the application’s user interface and integrate it with the Quarkus backend. The last part guides you through creating cluster configuration manifests and deploying them to Kubernetes as well as other alternatives, such as Fly.io. By the end of this full stack development book, you’ll be confident in your skills to combine the robustness of both frameworks to create and deploy standalone, fully functional web applications.
Publication date:
November 2022


Bootstrapping the Project

In this book, we’ll be creating a full-stack web application from scratch using Quarkus for the backend and React for the frontend. Quarkus is a new framework that aims to turn around the current Java ecosystem by simplifying the development of cloud-native applications and improving the developer experience. ReactJS is one of the most popular frontend JavaScript libraries. By the end of the book, you’ll be able to combine both frameworks to create and deploy a full-featured task manager web application.

In this chapter, we’ll provide a basic introduction to Quarkus and the tools that we’ll be using across this section. Then, we’ll create a Quarkus project from scratch and explain the basic architecture and structure of the application. By the end of this chapter, you should be able to create a Quarkus project and have a working development environment to implement the new features. You should also be able to package and run your application from your machine.

In this chapter, we’re going to cover the following topics:

  • What is Quarkus?
  • Setting up the work environment with IntelliJ IDEA
  • Bootstrapping a Quarkus application
  • Project structure and dependencies

Technical requirements

You will need the latest Java JDK LTS version (at the time of writing, Java 17). In this book, we will be using Fedora Linux, but you can use Windows or macOS as well.

You can download the full source code for this chapter from https://github.com/PacktPublishing/Full-Stack-Quarkus-and-React/tree/main/chapter-01.


What is Quarkus?

Java has been around for more than 25 years now. It is one of the most used programming languages, especially for developing enterprise applications. Its rich ecosystem, extensive and open community, and “write once, run anywhere” approach, have made it the de facto choice for creating enterprise software for decades.

However, things are changing now. We are in the era of the cloud, Kubernetes, and container images. Things such as startup time or memory footprint, which were not that significant before, are becoming more relevant these days. Java is losing its pace compared to other languages, which are specifically tailored for these new environments.

Quarkus is a new Java framework that was first released in 2019. It provides similar features to those of other mainstream Java frameworks such as Spring Boot or Micronaut. The main goals of Quarkus are to improve the application’s startup time, its memory footprint, and the developer experience.

Quarkus was built from the ground up to be cloud-native from the start. Regardless of how you package your application, boot time, and memory consumption, Quarkus performs much better than the alternatives. That’s why Quarkus is also known as Supersonic Subatomic Java.

Quarkus is built on top of long-lived proven standards and libraries. When Quarkus was designed, the team decided to rely on existing tools, frameworks, and standards instead of building something new from scratch. This was done so that developers don’t have to spend time learning something new and can focus on building more performant applications instead, taking advantage of their experience.

Quarkus uses the Java Enterprise Edition (EE) Contexts and Dependency Injection (CDI) standard for dependency injection; MicroProfile, a community-driven specification to optimize Java EE for a microservice architecture and for configuration and monitoring; Java Persistence API (JPA) annotations to define the object-relational mapping (ORM); Jakarta RESTful Web Services (JAX-RS) annotations to define the REST controllers; and many more technologies in a long, ever-growing list.

Quarkus brings a new developer experience to Java. One of the main drawbacks of Java when compared to other languages is the traditionally slow development cycles. A simple change to a line of code usually involves recompiling, repackaging, and restarting the application. This process could take anywhere from seconds to minutes, completely reducing the developer’s productivity. Quarkus aims at fixing this pain point by providing live coding, a unified configuration, a developer UI, and many more tools to bring joy back to developers.

Quarkus combines the traditional imperative coding style with the cloud-native friendly reactive coding style approach. Regardless of the type of application you are building, Quarkus provides first-class support for both paradigms. The cloud has brought new architectures to our systems, whether microservices, serverless, or event-driven. In this book, we’ll explore the new reactive non-blocking style, which will bring massive performance improvements when compared to the more classic imperative approach.

Quarkus is a free open source project that was initially released in March 2019. It is not only a fast-growing project in terms of adoption, but its community is soaring too. Despite its youth, it already has around 600 contributors (at the time of writing) and a growing ecosystem of extensions (https://github.com/quarkiverse). There’s already an extensive list of publications and bibliography available too.

Quarkus makes it extremely easy to create native executables for your platform. The framework provides almost transparent integration with GraalVM, a high-performance Java Development Kit (JDK) distribution that allows you to compile your Java code into a standalone binary executable.


Setting up the work environment with IntelliJ IDEA

In this book, we will develop a full-stack web application with Quarkus and React. Thus, we need to get started with writing the code for our application. We will be using IntelliJ IDEA for this purpose; however, you are free to use an integrated development environment (IDE) or editor of your choice. IntelliJ IDEA is a good choice because its ultimate version works well for both frontend and backend development.

IntelliJ IDEA is an IDE developed by JetBrains, which is based on the IntelliJ open source platform. The product is available in two flavors: the free community edition and the Ultimate Edition, which requires a paid subscription. However, there is an early access program that gives you free access to the early builds of the Ultimate version.

The easiest way to get IntelliJ IDEA is to go to the product page and download the appropriate bundle for your system: https://www.jetbrains.com/idea/download.


Bootstrapping a Quarkus application

Quarkus provides several options for bootstrapping an application. The easiest method involves using the https://code.quarkus.io page. You can also generate a new application by using the provided command-line interface (CLI) tool or even by running a Maven goal. We’ll be using the web interface since it’s the simplest approach and has a very straightforward wizard to customize the options and extension dependencies. However, you are free to explore other alternatives.

Maven goal

Maven is a build automation and project management tool mainly used in Java. A goal is a specific task that you can perform through Maven. Tasks such as compiling, packaging, and testing in Maven projects are performed via goal executions.

We are going to generate a Java 17 project with Maven and the latest available Quarkus version. Quarkus provides a web-based tool that allows you to create and customize an initial project. Let us take advantage of that by going through the following steps:

  1. Navigate with your web browser to https://code.quarkus.io.

You’ll be greeted with the following wizard:

Figure 1.1 – A screenshot of the code.quarkus.io web interface

Figure 1.1 – A screenshot of the code.quarkus.io web interface

  1. In the Group field, set the Maven project Group ID.

The generated project will include a package named with this value containing some sample starter code. I’m going to use com.example.fullstack, but you can use any other value.

  1. In the Artifact field, define the Maven artifact ID. In my case, I will use reactive.
  2. Select the base dependencies for our project. For now, we are only going to add a dependency to enable the implementation of HTTP endpoints. Since we want to take full advantage of Quarkus’ reactive features, we’ll use RESTEasy Reactive. You can filter through the dependencies by typing into the Filters text field and then checking the required dependency checkbox:
Figure 1.2 – A screenshot of the dependency selection section in the code.quarkus.io web interface

Figure 1.2 – A screenshot of the dependency selection section in the code.quarkus.io web interface

In the following chapters, we’ll be including more dependencies as we add functionality to the project.

  1. Click on the Generate your app button and download a ZIP package with the bootstrapped project.

Now that you have generated your Quarkus application, let us learn about the structure of the project and what features each of the project’s initial dependencies and plugins provides.


Project structure and dependencies

To start exploring the project’s structure, let us go through the following steps:

  1. Extract the generated ZIP package from the preceding bootstrapping exercise to the project’s definitive location. I extracted the ZIP to my dedicated directory for projects – you can extract it wherever you prefer but make sure you remember this location since this is the project we will be working on throughout the book.
  2. Open the project in IntelliJ IDEA or the IDE of your choice.

IntelliJ should automatically detect your Maven project and load its dependencies. In case it doesn’t, you can perform this step manually by right-clicking the pom.xml file and clicking on the Add as Maven Project menu item:

Figure 1.3 – A screenshot of IntelliJ IDEA and the Add as Maven Project context menu

Figure 1.3 – A screenshot of IntelliJ IDEA and the Add as Maven Project context menu

Let’s now explore the content and structure of the project and the provided sample code.

Maven Wrapper

The project includes a Maven Wrapper setup. Maven Wrapper is a tool that allows project users to run a consistent version of Maven across different build environments. The tool also allows you to run Maven without the need to have a global Maven installation. The project includes the .mvn directory and the mvnw and mvnw.cmd executable files.

You should be able to invoke Maven goals from a terminal in your project root. If you are in a Linux or macOS environment, you should be able to execute the wrapper by running ./mvnw. If you are on Windows, you can execute the Wrapper by running ./mvnw from a PowerShell terminal, or mvnw from a standard cmd.exe terminal. Now that we’ve seen the provided Maven Wrapper setup, let’s focus, examine the Maven project configuration more closely, and analyze what each section accomplishes.

Maven project (pom.xml)

The Maven project is defined in the Project Object Model pom.xml file. This XML file is the main unit of work for Maven and collects all the information and configuration details that will be used by Maven to build the project.

Let’s examine some of the sections of the pom.xml file that were bootstrapped for us from the Quarkus website.

Maven coordinates (GAV)

The Maven coordinates, also known as GAV, are the minimum required references for a project. These are the groupId, artifactId, and version fields that we defined in the web-based wizard when we bootstrapped the project:


These fields act as a unique identifier for the project and enable you to reference it in other projects just like a coordinate system.

Maven properties

The project comes with a set of predefined properties in an XML <properties> block. The following are the most important:

  • maven.compiler.release

This property sets the Java version for the project. In this case, both the sources and target classes will require a Java 17 version. This property is used by the Maven Compiler Plugin, and it was introduced in version 3.6 of the plugin. This property relies on the other compiler-plugin.version property, which you shouldn’t change – or at least make sure it’s always later than 3.6.

  • quarkus.platform.version

This property specifies the Quarkus version in use. Whenever a new Quarkus version is released, this is the property that you should update to upgrade your project. For patch versions and non-breaking releases, this change should be enough. For other version updates, you might need to change some parts of your code too.

Dependency management

The pom.xml file contains a dependency management block with the following content:


This definition is important to set the version of the Quarkus extension dependencies. It’s using placeholders for the following Maven properties found in the properties section to reference the effective dependency:


Under the hood, Maven is copying the dependency management section of the io.quarkus.platform:quarkus-bom, Quarkus’ Bill of Materials (BOM), artifact to the current project. This process enforces the use of a consistent version for all of the provided Quarkus extensions that we’ll see in the next section, Dependencies.


The following block in the project object model is the dependencies definition. These are the actual library dependencies of our project. Let’s see what each of the bootstrapped dependencies does.

RESTEasy Reactive

In this book, we are going to explore the new reactive capabilities of Quarkus. RESTEasy Reactive is a Quarkus-specific implementation of the JAX-RS specification based on Vert.x. It takes full advantage of Quarkus’ reactive non-blocking capabilities, which improve the overall application performance. The following code snippet defines the dependency for this library:


JAX-RS is a Java EE or Jakarta EE API specification that enables the implementation of REST web services. It provides common annotations such as @Path, @GET, and @POST, which can be used to annotate classes and methods to implement HTTP endpoints. If you’ve dealt with J2EE, Java EE, or Jakarta EE before, you might already be familiar with these annotations.

This highlights one of the main advantages of Quarkus. The learning curve is very gentle since most of it is based on proven community standards and libraries.

Quarkus ArC

Quarkus ArC is the dependency injection solution provided by Quarkus. It is based on the Java EE CDI 2.0 specification – again, a proven, long-lived standard. The following code snippet specifies this dependency:


One of the advantages of ArC, and most Quarkus extensions in general, is that it’s build-time oriented. Most analysis and optimizations happen at build time, so none of this processing needs to be performed during the application startup. The result is an application that starts up nearly instantly.

Quarkus JUnit5

Quarkus JUnit5 is the main dependency for the Quarkus testing framework. It provides the @QuarkusTest annotation, which is the main entry point for the test framework. The next code snippet configures this dependency:


We’ll examine this dependency and its features in more detail in Chapter 5, Testing Your Backend.

Rest Assured

Rest Assured is the last test dependency that was bootstrapped in the project. Although it’s not provided by Quarkus, it’s the recommended way to test its endpoints. The following code snippet is used to define this dependency; notice the groupId value is not io.quarkus anymore:


We’ll be using it to create the integration tests for our application.


Along with the more common Maven plugins, the build plugins section contains an entry for the Quarkus Maven plugin. This plugin provides Maven goals for most of the Quarkus features. Whenever we invoke any Maven command with a quarkus: prefix, this is the plugin that will be responsible for the execution.


The last section in the pom.xml file is the one dedicated to profiles. The bootstrapped project contains a single profile with the native ID. We can activate this profile either by using the Maven profile selection flag, -Pnative, or by providing a -Dnative system property (see the activation configuration):

Figure 1.4 – A screenshot of the beginning of the profiles section in pom.xml

Figure 1.4 – A screenshot of the beginning of the profiles section in pom.xml

The profile provides some specific configurations to run tests that partially override the one provided in the build or plugins section. However, the most important part is the quarkus.package.type property. This is the property that instructs Quarkus to build a native binary for our platform. When we package our application with this profile (./mvnw clean package -Pnative), we’ll get a binary file instead of a standard Java archive (JAR) package.

We’ll explore profiles in more detail in Chapter 6, Building a Native Image.

Source files

The bootstrapped project has the regular Java project structure. In addition to the pom.xml project file in the root directory, you will find a src subdirectory that contains the project sources.

Application properties

The application.properties file is located in the src/main/resources directory. This file contains the main configuration for our project. We’ll be modifying the application configuration and behavior by adding entries to it.

Under the hood, Quarkus uses SmallRye Config, which is an implementation of the Eclipse MicroProfile Configuration feature spec. This is another of the battle-tested standards on which Quarkus is based.

This is a standard property file. Each entry is added in a new line. For each line, the config key and the config value are separated by an = sign.

For example, the code to set the application server port would be as follows:


The application.properties file can also be used to define values that can be injected into your application.

Let’s say you defined the following property:


You could inject the preceding property into your application using the following snippet:

@ConfigProperty(name = "publisher.name")
String publisherName;


Quarkus provides the option to build and execute the application based on different profile configurations. Depending on the target environment, you might want to select a specific profile that provides a valid configuration for that environment.

Quarkus has three profiles – dev, which is activated in development mode, test, which is activated when the tests are executed, and prod, which is the default profile when the others don’t apply.

The same file is used for all profiles; to configure an option for a specific profile, you need to prefix the configuration key with % and the profile name, except for prod, which is the default profile and doesn’t require a prefix.

For the previous server port example, we can set the server port in dev mode as follows:


In general, we’ll be adding configuration for prod, and provide overrides for dev mode when needed.

Static resources

The project contains an index.html file in the src/main/resources/META-INF/resources directory. This file will be automatically served from the underlying application’s HTTP server. When pointing a browser to the root path of the application (http://localhost:8080), you will be greeted with this landing page that was bootstrapped for us:

Figure 1.5 – A screenshot of a browser pointing to http://localhost:8080

Figure 1.5 – A screenshot of a browser pointing to http://localhost:8080

By default, Quarkus will serve any static file that is located in this directory. However, for our application, we’ll be using an alternative method since this approach is not compatible with frontend routing. In Chapter 11, Quarkus Integration, I’ll show you how to implement an API gateway that will be used as an alternative to serving the static resources.

Java code

The bootstrapped project contains some sample code. A GreetingResource class is located in the standard src/main/java directory under the com.example.fullstack package. You will also find two tests for this class in the src/main/test directory under the same package: GreetingResourceTest and GreetingResourceIT. We will place the new code that we implement in the same root package grouped by features.

Docker files

The project contains some example Docker files in src/main/docker. These files can be used to create container images for your application. In Chapter 12, Deploying Your Application to Kubernetes, I’ll show you how to create container images for the application. However, we’ll be using Eclipse JKube, which requires a simpler configuration and doesn’t need these Docker files. JKube is a Maven plugin that generates all of the required configurations for your application to be able to deploy it to Kubernetes; for this reason, it’s not necessary to keep extra configuration files such as Docker or Kubernetes YAML files.

Now that we’ve seen the files and directory structure of the bootstrapped project, let us see how to perform the basic tasks that we will need to develop new features and deploy and run the application.

Development mode

For years, one of the main pain points for Java developers has been the lack of or very little support for hot reloading or live reloading. Traditionally, when you made some changes to your code, you had to recompile the application, package it, and redeploy it. This process was something that could take anywhere from a few seconds to several minutes or even hours in the worst cases. This is usually one of the disadvantages cited when people compare Java to other programming languages.

One of Quarkus’ main goals is bringing joy back to developers, so, naturally, this was one of the priority points to address. Quarkus development mode runs your application and monitors your code. Whenever you change any of the Java application source or resource files, Quarkus detects these changes and performs a hot deployment. You just need to refresh your browser for the changes to take effect.

We can start the development mode by running the quarkus:dev Maven goal from the project’s root directory as follows:

./mvnw quarkus:dev

You will see the following result:

Figure 1.6 – A screenshot of the IntelliJ terminal running Quarkus development mode

Figure 1.6 – A screenshot of the IntelliJ terminal running Quarkus development mode

If you check the preceding messages, you’ll notice that Quarkus automatically selected for us the dev profile and started the live coding mode.

We can now point our browser to the URL of the sample endpoint that was bootstrapped (http://localhost:8080/hello). If everything went well, the browser will show the Hello RESTEasy Reactive message:

Figure 1.7 – A screenshot of the browser pointing to the hello endpoint

Figure 1.7 – A screenshot of the browser pointing to the hello endpoint

If we open the GreetingResource class in our IDE, we should be able to see the definition for this endpoint. We can change the greeting message to something else:

public String hello() {
    return "Hello Quarkus live coding!";

In the traditional Java world, we would now need to recompile and redeploy the application to be able to see the changes. However, if we reload the browser window, our modified message should be visible.

Debugging in development mode

If you check the messages in Figure 1.6 closely, you’ll notice that Quarkus has also enabled a remote debugging port:

Listening for transport dt_socket at address: 5005

This means we can easily start a debug session from IntelliJ IDEA. For this, we need to create a new debug configuration from the Run > Edit Configurations… menu:

Figure 1.8 – A screenshot of the IntelliJ IDEA Run menu

Figure 1.8 – A screenshot of the IntelliJ IDEA Run menu

From the Run/Debug Configurations screen, we need to create a new Remote JVM Debug configuration. The default options should be fine for Quarkus, so we only need to specify a name for this configuration:

Figure 1.9 – A screenshot of IntelliJ IDEA Quarkus debug configuration

Figure 1.9 – A screenshot of IntelliJ IDEA Quarkus debug configuration

Once we save the configuration, we can run it and should be able to set a breakpoint on our endpoint definition. If we reload the browser window, the debugger should stop at our breakpoint.

When combined with easy debugging, live reloading is very powerful and will certainly improve our developer performance. Now that we know how to use the Quarkus development mode to implement and debug our code, let us see how to run the tests for our application.

Continuous testing

One of Quarkus 2.X’s features is its ability to run tests continuously. This is a feature borrowed from other programming languages, such as Ruby, that have offered it for a long time. It is also a further step in achieving Quarkus’s goal to bring back developer joy to Java.

For users who practice test-driven development (TDD), this will massively improve their development cycle performance. In a usual TDD process, developers first write a test for a feature and then implement the code that will make that test pass. This process is repeated for each of the properties of the feature and for each code refactor. Continuous test execution provides instant feedback and allows the developer to concentrate and focus on the implementation and not on the process.

When Quarkus is run in continuous testing mode, it will detect code changes to both code and tests. For each change it detects, it will re-run the relevant tests for the affected code.

Just as with the development mode, we can run a Maven command to start the continuous testing mode as follows:

./mvnw quarkus:test

If you recall, in the Development mode section, we changed the greeting in the GreetingResource class but we didn’t change the test. The first thing we’ll see once we invoke the quarkus:test Maven goal is a test failure:

Figure 1.10 – A screenshot of quarkus:test failing to be invoked

Figure 1.10 – A screenshot of quarkus:test failing to be invoked

We can now open GreetingResourceTest and update the expected response body to the new greeting, Hello Quarkus live coding!:

public void testHelloEndpoint() {
         .body(is("Hello Quarkus live coding!"));

If we save the changes, the test should automatically re-run and it will be green again:

Figure 1.11 – A screenshot of quarkus:test passing invocation

Figure 1.11 – A screenshot of quarkus:test passing invocation

Expanding on the TDD use case, if there was a new requirement to expose a /hello/world endpoint, the first step would be to add a new test:

public void testHelloWorldEndpoint() {
      .body(is("Hello world!"));

There is no implementation yet, so the execution would fail. We could then implement the new endpoint to make the test pass as follows:

public String helloWorld() {
    return "Hello world!";

Once tests pass, the next step could be to retrieve the endpoint value from an external service. So, we would modify the test, then the implementation, and start the cycle again. It should be clear now how the experience of the overall process is notably improved by continuous testing.

TDD ensures that the features defined in the provided specs are working using unit tests. This allows you to write code with fewer bugs and spend less time on long debugging sessions trying to fix errors. Now that we’ve seen how to perform TDD in Quarkus, let us see how to package the application for its distribution.

Packaging the application

The final step to being able to distribute and run the application would be to package it. Besides the native mode, which we already analyzed in the Profiles section, Quarkus offers the following package types:

  • fast-jar: This is the default packaging mode. It creates a highly optimized runner JAR package, along with a directory and its dependencies.
  • uber-jar: This mode will generate a fat JAR containing all of the required dependencies. This JAR package is suitable for distribution of the application on its own.
  • native: This mode uses GraalVM to package your application into a single native binary executable file for your platform.
  • native-sources: This type is intended for advanced users. It generates the files that will be needed by GraalVM to create the native image binary. It’s like the native packaging type but stops before triggering the actual GraalVM invocation. This allows performing the GraalVM invocation in a separate step, which might be useful for CI/CD pipelines.

You can control the packaging mode by setting the quarkus.package.type Maven property. You can set this property in the pom.xml properties section or via the command line when running the Maven commands:

./mvnw -D"quarkus.package.type=uber-jar" clean package

For the moment, we’ll be using the default packaging mode. You can package the application running the following command:

./mvnw clean package

If everything went well, you should now be able to run the application by executing the following:

java -jar target/quarkus-app/quarkus-run.jar

You should now be able to navigate to http://localhost:8080 or any of the HTTP endpoints we created in the previous steps.



In this chapter, we gave a quick introduction to Quarkus and saw what its main advantages and breakthroughs for the Java ecosystem are. We created a new Quarkus project using the Quarkus website and opened it in IntelliJ IDEA. We reviewed the contents and structure of the bootstrapped project. We checked the dependencies, plugins, and the provided source code, and we learned how to package and run the sample application.

You should now have a broad view of Quarkus and be ready to start implementing the full-stack web application that we’ll be developing throughout the book. In the next chapter, we’ll see how to add a persistence layer to the task manager application, define the entity classes, and connect it to a database.



  1. What is Quarkus?
  2. How do you create a Quarkus project from scratch?
  3. How do you run a Quarkus project in development mode?
  4. What is TDD?
  5. How do you package a Quarkus project?
About the Author
  • Marc Nuri San Felix

    Marc started his career as a freelance web application developer, creating and maintaining software for the transportation/courier industry. A few years ago Marc started working as an employee for different companies where he has helped build scalable web applications for different industries (retail, procurement software, e-commerce, etc.). He is now a professional Open Source developer focused on the creation and maintenance of developer tools for Java developers and Kubernetes.

    Browse publications by this author
Full Stack Quarkus and React
Unlock this book and the full library FREE for 7 days
Start now