5 minutes pour… monter une API REST avec Quarkus

Avant de se lancer dans le vif du sujet, rappelons que Quarkus est un framework d’applications Java, conçu pour fonctionner nativement avec Kubernetes, OpenJDK HotSpot et GraalVM.

La compilation native lui permet d’optimiser Java spécifiquement pour les conteneurs afin d’en faire une plateforme efficace pour les environnements serverless, cloud et Kubernetes.

Prérequis

Avant de commencer assurez vous d’avoir les éléments suivants installés et configurés :

Maintenant que tout est prêt lançons nous !

Première minute : Initialisation

L’équipe de Quarkus étant généreuse, elle nous met à disposition un utilitaire qui nous permet d’initialiser rapidement un projet : https://code.quarkus.io/

On renseigne les infos génériques, on choisit les extensions et on génère un projet vierge :

  • RESTEasy JAX-RS : Implémentation de Jakarta RESTful Web Services (JAX-RS)
  • RESTEasy Jackson : Support du format JSON
  • MongoDB with Panache : Accès aux données stockées dans la base MongoDB
Sélectionner les extensions :
RESTEasy JAX-RS
RESTEasy Jackson
MongoDB with Panache
https://code.quarkus.io/

Deuxième minute : Configuration et lancement

On décompresse l’archive téléchargée et on l’ouvre dans notre IDE.

On ajoute dans le fichier application.properties les lignes suivantes afin de configurer l’accès à notre base de données Mongo :

# Configuration de MongoDB client
quarkus.mongodb.connection-string=<url_bdd_mongo>

# Nom de la base. Obligatoire si on ne spécifie pas le nom de la base avec l'annotation @MongoEntity
quarkus.mongodb.database=<nom_database>

Ceci étant fait on lance la commande suivante qui va compiler et démarrer notre projet, cette commande peut être retrouvée dans le fichier README.md du projet :

./mvnw compile quarkus:dev

On peut alors vérifier que tout fonctionne en consultant la console de dév mise à disposition par Quarkus : http://localhost:8080/q/dev/

Quarkus dev console
Quarkus dev console

Cette console nous permet :

  • de voir les extensions utilisées par notre projet
  • d’accéder à la vue des beans chargés dans notre contexte applicatif
  • de voir et de modifier à chaud la configuration de notre projet, dont celle que l’on vient d’ajouter dans notre fichier application.properties

Ne touchez à rien et ne coupez pas votre commande shell ! On va profiter du système de live reloading qu’offre Quarkus dans la suite de notre aventure.

Troisième minute : Initialisation de l’API REST

Pour faire simple et original nous allons nous créer une API de gestion de livre (c’est dans les vieux pots…).

Ajoutons un package, j’ai nommé le mien fr.kanoma.quikies.quarkus.api et créons la classe suivante :

package fr.kanoma.quikies.quarkus.api;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

import org.bson.types.ObjectId;

import fr.kanoma.quikies.quarkus.api.repository.BookEntity;
import fr.kanoma.quikies.quarkus.api.repository.LibraryRepository;

@Path("/library")
public class LibraryController {
    @GET
    @Path("/about")
    public String about() {
        String aboutMessage = "Library version 0.1";
        return aboutMessage;
    }
}

On appel alors notre nouveau endpoint : http://localhost:8080/library/about et hop ça marche ! Pas besoin de relancer de commande Maven et d’attendre, le code est interprété à chaud.

Quatrième minute : Accès aux données

Ajoutons un peu de contenu à notre projet en lui permettant de communiquer avec notre base MongoDB.

Pour ce faire, nous allons ajouter deux nouvelles classes :

  • BookEntity.java, qui va représenter un livre dans notre bibliothèque virtuelle
  • LibraryRepository.java, qui va correspondre à notre interface d’accès aux ressources de la base MongoDB
package fr.kanoma.quikies.quarkus.api.repository;

import com.fasterxml.jackson.annotation.JsonProperty;
import org.bson.types.ObjectId;
import io.quarkus.mongodb.panache.MongoEntity;

// L' annotation ci-dessous nous permet de définir la collection Mongo qui sera relative à nos entités Book
@MongoEntity(collection="book")
public class BookEntity {
    // On défini le champ qui sera notre identifiant technique pour notre entité
    public ObjectId id;

    // On ajoute l'annotation ci-dessous préciser le format JSON qui sera retourné par nos endpoints REST
    @JsonProperty
    public String name;

    @JsonProperty
    public String desc;

    @JsonProperty
    public String author;
}
package fr.kanoma.quikies.quarkus.api.repository;

import javax.enterprise.context.ApplicationScoped;
import io.quarkus.mongodb.panache.PanacheMongoRepository;

// L'annotation ci-dessous permet de définir que notre repository sera un singleton 
@ApplicationScoped
public class LibraryRepository implements PanacheMongoRepository<BookEntity> {
    
    }
}

Cinquième minute : Exposition des ressources

Maintenant que nous avons tout ce qu’il nous faut pour accéder à nos données, nous allons ajouter nos endpoints CRUD.

Je suis sympa (et pour tenir le format ^^), je vous épargne l’écriture de cette partie, voici le code de la classe LibraryController.java :

package fr.kanoma.quikies.quarkus.api;

import java.util.List;
import javax.inject.Inject;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.bson.types.ObjectId;
import fr.kanoma.quikies.quarkus.api.repository.BookEntity;
import fr.kanoma.quikies.quarkus.api.repository.LibraryRepository;

@Path("/library")
public class LibraryController {

    @Inject
    private LibraryRepository libraryRepository;

    @GET
    @Path("/about")
    public String about() {
        String aboutMessage = "Library version 0.1";
        return aboutMessage;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<BookEntity> getAll() {
        return libraryRepository.findAll().list();
    }

    @GET
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public BookEntity get(@PathParam("id") ObjectId id) {
        return libraryRepository.findById(id);
    }

    @POST
    public void add(BookEntity badge) {
        libraryRepository.persist(badge);
    }

    @DELETE
    @Path("/{id}")
    public void delete(@PathParam("id") ObjectId id) {
        libraryRepository.deleteById(id);
    }
}

Désormais nous pouvons ajouter un livre à notre bibliothèque :

curl --header "Content-Type: application/json" \
   --request POST \
   --data '{"name":"La jeunesse d un mage","author":"Ed Greenwood", "desc":"Tome 1"}' \
   http://localhost:8080/library/

et consulter tous nos livres disponibles : http://localhost:8080/library/

ou en consulter et/ou en supprimer un en particulier via son identifiant.

Conclusion

Nous voici arrivé au bout de ces 5 minutes et qu’avons nous pu apprendre ?

Qu’on peut faire un CRUD en 5 minutes ? Non, bien que ce code soit magnifique, ce n’est pas ce qui nous importe le plus.

Nous avons pu voir qu’avec Quarkus on peut développer et tester à chaud, sans de longues reconstructions ( et même avec Maven 😀 ).

Que Quarkus propose des extensions qui permettent de répondre à nos besoins.

Les extensions disponibles peuvent supporter la programmation réactive via RESTEasy Reactive ou encore d’adresser une instance Kafka via Apache Kafka Client. Je vous laisse parcourir la liste et trouver votre bonheur : https://code.quarkus.io/.

Quarkus a aussi des avantages au niveau runtime, à savoir :

  • Une consommation mémoire faible
  • Un temps de réponse rapide, qui se compte en millisecondes, sur le premier appel

Quarkus mérite qu’on lui accorde bien plus que 5 minutes et je vous invite vivement à le faire 😉

S’abonner
Notifier de
guest

1 Commentaire
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
GncDev
GncDev
1 année

merci!