Exercice - Créer une application Quarkus

Effectué

Dans cette unité, vous créez une application Quarkus basique. Vous utilisez Maven pour démarrer l’application et un environnement de développement intégré (IDE) de votre choix pour modifier le code. Utilisez un terminal de votre choix pour exécuter le code. Vous utilisez Docker pour démarrer une base de données PostgreSQL locale afin de pouvoir exécuter et tester l’application localement.

Générer l’application Quarkus à l’aide de Maven

Il existe plusieurs façons pour créer une structure de projet Quarkus. Vous pouvez utiliser l'interface web Quarkus, un plug-in IDE ou le plug-in Maven Quarkus. Utilisons le plug-in Maven pour générer la structure du projet.

Vous générez votre application avec plusieurs dépendances :

  • Dépendance resteasy pour exposer un point de terminaison REST
  • Dépendance jackson pour sérialiser et désérialiser JSON
  • La dépendance hibernate pour interagir avec la base de données
  • Dépendance postgresql pour se connecter à la base de données PostgreSQL
  • Dépendance docker pour générer une image Docker

Vous n’avez pas besoin de spécifier des dépendances Azure, car vous exécutez votre application localement, puis déployez une version conteneurisée sur Azure Container Apps.

À l’invite de commandes, générez l’application de tâches :

mvn -U io.quarkus:quarkus-maven-plugin:3.19.0:create \
    -DplatformVersion=3.18.4 \
    -DprojectGroupId=com.example.demo \
    -DprojectArtifactId=todo \
    -DclassName="com.example.demo.TodoResource" \
    -Dpath="/api/todos" \
    -DjavaVersion=17 \
    -Dextensions="resteasy-jackson, hibernate-orm-panache, jdbc-postgresql, docker"

Cette commande crée un nouveau projet Quarkus. Il génère une structure de répertoires Maven (src/main/java pour le code source et src/test/java pour les tests). Il crée des classes Java, des tests et des fichiers Dockerfiles. Il génère également un fichier pom.xml avec toutes les dépendances nécessaires (Hibernate, RESTEasy, Jackson, PostgreSQL et Docker) :

  <dependencies>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-hibernate-orm-panache</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-jackson</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-jdbc-postgresql</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-container-image-docker</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-arc</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-hibernate-orm</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-junit5</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

Remarque

Toutes les dépendances dans le fichier pom.xml sont définies dans le boM de Quarkus (facture de matériaux) io.quarkus.platform:quarkus-bom.

Coder l’application

Ensuite, renommez la classe MyEntity.java générée en Todo.java (située dans le même dossier que le fichier TodoResource.java). Remplacez le code existant par le code Java suivant. Il utilise l’API de persistance Java (jakarta.persistence.* package) pour stocker et récupérer des données à partir de votre serveur PostgreSQL. Il utilise également Hibernate ORM avec Panache (hérite de io.quarkus.hibernate.orm.panache.PanacheEntity) pour simplifier la couche de persistance.

Vous utilisez une entité JPA (@Entity) pour mapper l’objet java Todo directement à la table Todo PostgreSQL. Le point de terminaison REST TodoResource crée ensuite une classe d’entité Todo et la conserve. Cette classe est un modèle de domaine qui est mappé à la table Todo. La table est créée automatiquement par JPA.

L’extension de PanacheEntity vous offre un certain nombre de méthodes génériques de création, lecture, mise à jour et suppression (CRUD) pour votre type. Vous pouvez donc effectuer des opérations telles que l’enregistrement et la suppression d’objets Todo dans une seule ligne de code Java.

Ajoutez le code suivant à l’entité Todo :

package com.example.demo;

import io.quarkus.hibernate.orm.panache.PanacheEntity;

import jakarta.persistence.Entity;
import java.time.Instant;

@Entity
public class Todo extends PanacheEntity {

    public String description;

    public String details;

    public boolean done;

    public Instant createdAt = Instant.now();

    @Override
    public String toString() {
        return "Todo{" +
                "id=" + id + '\'' +
                ", description='" + description + '\'' +
                ", details='" + details + '\'' +
                ", done=" + done +
                ", createdAt=" + createdAt +
                '}';
    }
}

Pour gérer cette classe, mettez à jour le TodoResource afin qu’il puisse publier des interfaces REST pour stocker et récupérer des données à l’aide de HTTP. Ouvrez la classe TodoResource et remplacez le code par les éléments suivants :

package com.example.demo;

import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
import jakarta.ws.rs.core.UriInfo;
import org.jboss.logging.Logger;

import java.util.List;

@Path("/api/todos")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public class TodoResource {

    @Inject
    Logger logger;

    @Inject
    UriInfo uriInfo;

    @POST
    @Transactional
    public Response createTodo(Todo todo) {
        logger.info("Creating todo: " + todo);
        Todo.persist(todo);
        UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder().path(todo.id.toString());
        return Response.created(uriBuilder.build()).entity(todo).build();
    }

    @GET
    public List<Todo> getTodos() {
        logger.info("Getting all todos");
        return Todo.listAll();
    }
}

Exécuter l’application

Lorsque vous exécutez l’application en mode développement, Docker doit être en cours d’exécution. Cela est dû au fait que Dockerus détecte que vous avez besoin d’une base de données PostgreSQL (en raison de la dépendance PostgreSQL quarkus-jdbc-postgresql déclarée dans le fichier pom.xml), télécharge l’image Docker PostgreSQL et démarre un conteneur avec la base de données. Il crée ensuite automatiquement la table Todo dans la base de données.

Vérifiez que Docker s’exécute localement sur votre ordinateur et exécutez l’application to-do à l’aide de cette commande :

cd todo
./mvnw quarkus:dev    # On Mac or Linux
mvnw.cmd quarkus:dev  # On Windows

L’application Quarkus doit démarrer et se connecter à votre base de données. La sortie suivante doit s’afficher :

2025-02-28 08:38:33,418 INFO  [io.qua.dat.dep.dev.DevServicesDatasourceProcessor] (build-28) Dev Services for default datasource (postgresql) started - container ID is ce37977203b0
2025-02-28 08:38:33,421 INFO  [io.qua.hib.orm.dep.dev.HibernateOrmDevServicesProcessor] (build-6) Setting quarkus.hibernate-orm.database.generation=drop-and-create to initialize Dev Services managed database
__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
2025-02-28 08:38:35,278 INFO  [io.quarkus] (Quarkus Main Thread) todo 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.18.4) started in 5.367s. Listening on: http://localhost:8080

2025-02-28 08:38:35,280 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2025-02-28 08:38:35,280 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-postgresql, narayana-jta, resteasy, resteasy-jackson, smallrye-context-propagation, vertx]

--
Tests paused
Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>

Pour tester l’application, vous pouvez utiliser cURL.

Dans un terminal distinct, créez un élément to-do dans la base de données avec la commande suivante. Vous devez voir le log dans la console Quarkus.

curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done": "true"}' \
    http://127.0.0.1:8080/api/todos

Cette commande doit retourner l’élément créé (avec un identificateur) :

{"id":1,"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done":true,"createdAt":"2025-02-26T07:27:30.093447Z"}

Créez une deuxième to-do à l’aide de la commande cURL suivante :

curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"description":"Take Azure Container Apps MS Learn","details":"Take the ACA Learn module","done": "false"}' \
    http://127.0.0.1:8080/api/todos

Ensuite, récupérez les données à l’aide d’une nouvelle requête cURL :

curl http://127.0.0.1:8080/api/todos

Cette commande retourne la liste des éléments to-do, y compris les éléments que vous avez créés :

[ 
  {"id":1,"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done":true},
  {"id":2,"description":"Take Azure Container Apps MS Learn","details":"Take the ACA Learn module","done":false}
]

Tester l’application

Pour tester l’application, vous pouvez utiliser la classe TodoResourceTest existante. Il doit tester le point de terminaison REST. Pour tester le point de terminaison, il utilise RESTAssured. Remplacez le code dans la classe TodoResourceTest par le code suivant :

package com.example.demo;

import io.quarkus.test.junit.QuarkusTest;
import static io.restassured.RestAssured.given;
import static jakarta.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import org.junit.jupiter.api.Test;

@QuarkusTest
class TodoResourceTest {

    @Test
    void shouldGetAllTodos() {
        given()
                .when().get("/api/todos")
                .then()
                .statusCode(200);
    }

    @Test
    void shouldCreateATodo() {
        Todo todo = new Todo();
        todo.description = "Take Quarkus MS Learn";
        todo.details = "Take the MS Learn on deploying Quarkus to Azure Container Apps";
        todo.done = true;

        given().body(todo)
                .header(CONTENT_TYPE, APPLICATION_JSON)
                .when().post("/api/todos")
                .then()
                .statusCode(201);
    }
}

Lorsque vous testez l'application, Docker Desktop doit être en cours d'exécution, car Quarkus détecte qu'il a besoin de la base de données PostgreSQL pour les tests. Testez l’application à l’aide de cette commande :

./mvnw clean test    # On Mac or Linux
mvnw.cmd clean test  # On Windows

Vous devriez voir un résultat qui devrait ressembler à ceci :

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.demo.TodoResourceTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------