Welcome to QuarkusIO, the lastest project for supersonic Java! Quarkus features a Cloud Native, Container first, Microservice ready framework for writing Java applications based on the standards and frameworks you are using today (Hibernate, RESTEasy, Camel, Vert.X etc).

What does it mean ?

  • Container First: Minimal footprint Java applications optimal for running in containers
  • Cloud Native: Embraces 12 factor architecture in environments like Kubernetes.
  • Microservice First: Brings lightning fast startup time and code turn around to Java apps

Here is a bird's eye view of the Project:

As you can see, one of the most interesting aspect of quarkus is that you can build native executables using GraalVM. That makes Quarkus applications ideal for containers and serverless workloads. In this first tutorial we will learn how to build a Quarkus REST application using the Maven tooling available and add a minimal of compexity to it.

Building your first Quarkus application

Requirements to build a Quarkus Java Applications:

  • JDK 8 or 11+ installed with JAVA_HOME configured appropriately

  • Apache Maven 3.6.2+

Quarkus applications can be quickly bootstrapped using the Maven or Gradle plugin available. The plugin will generate a minimal project structure with a sample REST Endpoint and the Quarkus's Maven dependencies included in the configuration file. Let's assume you are using Maven:

mvn io.quarkus:quarkus-maven-plugin:1.4.1.Final:create -DprojectGroupId=com.sample -DprojectArtifactId=hello-quarkus -DclassName="com.sample.QuarkusEndpoint" -Dpath="/hello" 

The following project structure will be created:

├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
    ├── main
    │   ├── docker
    │   │   ├── Dockerfile.jvm
    │   │   └── Dockerfile.native
    │   ├── java
    │   │   └── com
    │   │       └── sample
    │   │           └── QuarkusEndpoint.java
    │   └── resources
    │       ├── application.properties
    │       └── META-INF
    │           └── resources
    │               └── index.html
    └── test
        └── java
            └── com
                └── sample
                    ├── NativeQuarkusEndpointIT.java
                    └── QuarkusEndpointTest.java

The most interesting items are:

  • The QuarkusEndpoint.java containing the Hello REST Endpoint
  • Two Dockerfile : Dockerfile.jvm to build the application as a Container using a Java image. Dockerfile.native to build a native image of the application.
  • An index.html file to remind you that you can add static files (HTML, images, Javascript) in that folder
  • Two Test classes added under the folder "test" to test the application with Java or as native executable.
  • A file named application.properties which is the main configuration file in Quarkus

Here is the quintessential REST Endpoint, which returns a text string upon invocation of the "hello()" GET Resource.

package com.sample;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

public class QuarkusEndpoint {

    public String hello() {
        return "hello";

The pom.xml file, reflects the libraries needed to bootstrap the project. Here is the dependencies section of it:


You can build and run your project from the root folder with:

mvn clean compile quarkus:dev

The application will bootstrap Quarkus in a snap:

[INFO] Running com.sample.QuarkusEndpointTest
2019-03-14 16:46:19,743 INFO  [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation
2019-03-14 16:46:20,292 INFO  [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 549ms
2019-03-14 16:46:20,610 INFO  [io.quarkus] (main) Quarkus 1.0.0.Final started in 0.294s. Listening on:

You can test it with:

curl http://localhost:8080/hello

That will return the "Hello" String

Debugging and Hot Deploying with Quarkus

As you can see, we have launched Quarkus with quarkus:dev which runs Quarkus in development mode. This enables hot deployment with background compilation, which means that when you modify your Java files your resource files and refresh your browser these changes will automatically take effect. This works too for resource files like the configuration property file. Refreshing the browser triggers a scan of the workspace, and if any changes are detected the Java files are recompiled and the application is redeployed; your request is then serviced by the redeployed application. If there are any issues with compilation or deployment an error page will let you know.

Also, in that mode, Quarkus will listen for a debugger on port 5005. If your want to wait for the debugger to attach before running you can pass -Ddebug on the command line. If you don’t want the debugger at all you can use -Ddebug=false.

Building a more complex application

We will now learn how to build a slightly more complex Quarkus application which still uses a REST Endpoint but has a minimal UI to insert data in memory.

You can re-use the same project you have just built, or create a new one from scratch. Start by adding a Java Bean to be used as Domain class:

package com.sample;

import java.util.Objects;

public class Person {

    String name;
    String surname;

    public Person( ) {  }

    public String getName() {
        return name;
    public String getSurname() {  return surname;  }
    public void setName(String name) {
        this.name = name;
    public void setSurname(String surname) {
        this.surname = surname;
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", surname='" + surname + '\'' +

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) &&
                Objects.equals(surname, person.surname);

    public int hashCode() {
        return Objects.hash(name, surname);

Now a REST Endpoint to save this object in a Collection:

package com.sample;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Set;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

public class RESTEndpoint {

    private Set<Person> persons = Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));

    public Set<Person> list() {
        return persons;

    public Set<Person> add(Person person) {
        System.out.println("Saving: " +person);
        return persons;


Basically, we have added a GET method to retrieve the list of Person, and a POST method to save a new Person in the Set.

As the above class can Produce and Consume JSON, we need to include also the quarkus-resteasy-jsonb artifact to our dependencies:


As it is, our application it is ready to be tested:

mvn clean compile quarkus:dev

You can add a new entry with cURL, passing as data the JSON to be consumed:

curl -d '{"name":"john", "surname":"black"}' -H "Content-Type: application/json" -X POST

We can check that the data is available, with the corresponding GET request:


Adding an UI to our Quarkus project

Finally, we can show how we can add Web application pages to our project. In order to do that, we need to add HTML pages under the following path:

│   └── resources
│       └── META-INF
│           └── resources

For example, we will add an HTML page using AngularJS to display the data in Tabular format, with a Form to add new items via POST:

<!doctype html>
    <meta charset="utf-8"/>
    <title>Quarkus REST service</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/wingcss/0.1.8/wing.min.css"/>
    <!-- Load AngularJS -->
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script type="text/javascript">
      var app = angular.module("PersonManagement", []);

      //Controller Part
      app.controller("PersonManagementController", function ($scope, $http) {

        //Initialize page with empty data
        $scope.persons = [];

        $scope.form = {
          name: "",
          surname: ""

        //Now load the data from server

        //HTTP POST methods for add data
        $scope.add = function () {
          var data = { "name": $scope.form.name, "surname": $scope.form.surname };

            method: "POST",
            url: '/persons',
            data: angular.toJson(data),
            headers: {
              'Content-Type': 'application/json'
          }).then(_success, _error);

        //HTTP GET- get all persons collection
        function _refreshPageData() {
            method: 'GET',
            url: '/persons'
          }).then(function successCallback(response) {
            $scope.persons = response.data;
          }, function errorCallback(response) {

        function _success(response) {

        function _error(response) {
          alert(response.data.message || response.statusText);

        //Clear the form
        function _clearForm() {
          $scope.form.name = "";
          $scope.form.surname = "";
<body ng-app="PersonManagement" ng-controller="PersonManagementController">

<div class="container">
    <h1>Quarkus REST Service</h1>

    <form ng-submit="add()">
        <div class="row">
            <div class="col-6"><input type="text" placeholder="Name" ng-model="form.name" size="60"/></div>
        <div class="row">
            <div class="col-6"><input type="text" placeholder="Surname" ng-model="form.surname" size="60"/></div>
        <input type="submit" value="Save"/>

    <h3>Person List</h3>
    <div class="row">
        <div class="col-4">Name</div>
        <div class="col-8">Surname</div>
    <div class="row" ng-repeat="person in persons">
        <div class="col-4">{{ person.name }}</div>
        <div class="col-8">{{ person.surname }}</div>


Again, run your application with:

mvn clean compile quarkus:dev

And see it in action at: http://localhost:8080

Quarkus io tutorial wildfly quarkus

Now experiment changing anything in the HTML page, for example the Heading contained in it. As the application is running in Development mode, you will see your changes without restarting your app!

Quarkus io tutorial wildfly quarkus


In this first tutorial about QuarkusIO we have covered the basic set up of an application and the tooling which can be used to bootstrap your projects. Continue learning QuarkusIO in this tutorial which shows how to create a native application: Building Container-ready native applications with Quarkus

Source code for this example: https://github.com/fmarchioni/mastertheboss/tree/master/quarkus/hello-quarkus

References: https://quarkus.io/