Swag now available

Creating a Project

Creating a Basic Project

Let's create the basic Quarkus Hello World application and include the necessary qute extensions:

mvn io.quarkus:quarkus-maven-plugin:1.6.1.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=qute \
    -DclassName="org.acme.qute.HelloResource" \
    -Dextensions="quarkus-resteasy-qute,quarkus-vertx-web,quarkus-qute,quarkus-scheduler" \
Note: The first time you create an app, new dependencies may be downloaded via maven and take a minute or so. This should only happen once, after that things will go even faster.

This will use the Quarkus Maven Plugin and generate a basic Maven project for you in the qute subdirectory and include the quarkus-resteasy-qute extension which includes the templating engine and integration with JAX-RS via RestEasy. We've also included a few other extensions we'll use later on.  

Once generated, look at the pom.xml file. You will find the import of the Quarkus BOM, allowing you to omit specifying the specific version on the different Quarkus dependencies.


Before moving on, change to the newly created project directory:
cd qute

Starting the Application

With the basics in place, start the application:

mvn compile quarkus:dev

Once the dependencies have finished downloading (again, this will only occur on the first compile), you'll see the running application:

__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2021-04-28 10:55:57,260 INFO [io.qua.sch.run.SimpleScheduler] (Quarkus Main Thread) No scheduled business methods found - Simple scheduler will not be started
2021-04-28 10:55:57,309 INFO [io.quarkus] (Quarkus Main Thread) qute 1.0-SNAPSHOT on JVM (powered by Quarkus 1.6.1.Final) started in 0.918s. Listening on:
2021-04-28 10:55:57,310 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2021-04-28 10:55:57,310 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, mutiny, qute, resteasy, resteasy-qute, scheduler, smallrye-context-propagation, vertx, vertx-web]

Note the amazingly fast startup time! The app is now running "locally" on your machine.  

Test that the app is running by opening a new terminal and accessing the simple hello endpoint:
curl http://localhost:8080/hello

You should see the output:


Creating a Basic Template

Let's start with a very simple template. Create a new directory to hold your templates by clicking this command:

mkdir -p src/main/resources/templates

Create a file in the newly created directory (src/main/resources/templates) named hello.txt with the contents:

Hello {name}!

The snippet {name} is a value expression that is evaluated when the template is rendered.

Note: By default, all files located in the src/main/resources/templates directory and its subdirectories are registered as templates. Templates are validated during startup and watched for changes in the development mode.

Creating a REST Endpoint

Now let’s inject the "compiled" template in the resource class.  

Open the file src/main/java/org/acme/qute/HelloResource.java.


Replace the existing contents of that file with the following:
package org.acme.qute;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import io.quarkus.qute.TemplateInstance;
import io.quarkus.qute.Template;

public class HelloResource {

    Template hello;

    public TemplateInstance get(@QueryParam("name") String name) {
        return hello.data("name", name);


A few notes on the replacement code:


  • If there is no @ResourcePath qualifier provided when using @Inject, the field name is used to locate the template.
  • The Template.data() method returns a new template instance that can be customized before the actual rendering is triggered. In this case, we put the name value under the key name. The data map is accessible during rendering.
  • Note that we don’t explicitly trigger the rendering - this is done automatically by a special ContainerResponseFilter implementation.

Testing the Endpoint

With the application already running in Live Coding mode, we can render the template by calling the endpoint. In a new terminal, run the following command to invoke the endpoint:

curl http://localhost:8080/hello?name=Jason

You should see:

Hello Jason!

The template was rendered, replacing the {name} expression with the value passed in with hello.data("name", name);  

This is the basic syntax and idea, which originated in many other popular and well-known technologies.


Now let's explore some new features based on Quarkus principles.