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 :
- votre IDE préféré
- Maven
- Java version 11+
- une instance mongoDB disponible. Vous pouvez en créer une rapidement et gratuitement sur https://www.mongodb.com/cloud/atlas
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
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/
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 😉
Technical Lead chez KANOMA
merci!