Quarkus : Java cloud-natif pour les microservices modernes
Guide de démarrage avec Quarkus : démarrage ultrarapide, mode natif GraalVM, Panache ORM, injection de dépendances CDI et comparaison avec Spring Boot pour vos microservices.
Quarkus est un framework Java conçu spécifiquement pour le cloud et les environnements conteneurisés. Là où Spring Boot démarre en 2-5 secondes, Quarkus démarre en 50-200 millisecondes. En mode natif (GraalVM), le démarrage tombe à 10-50 ms avec une consommation mémoire 3 à 10 fois inférieure. Dans un environnement serverless ou Kubernetes avec scaling rapide, c’est une différence critique.
Pourquoi Quarkus en 2025 ?
Serverless : AWS Lambda, Azure Functions et Google Cloud Run facturent au temps d’exécution. Un cold start Spring Boot de 4 secondes coûte cher et dégrade l’expérience. Quarkus natif démarre en 50ms.
Kubernetes horizontal scaling : quand K8s démarre de nouvelles instances pour absorber la charge, le temps de disponibilité de ces instances importe. Des pods Quarkus prêts en 100ms vs 5 secondes changent la réactivité du scaling.
Empreinte mémoire : en microservices, vous avez des dizaines de services. Chaque MB économisé multiplie son impact. Un service Quarkus natif consomme 30-60 MB vs 200-400 MB pour Spring Boot.
Créer un projet Quarkus
# Via Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.9.0:create \
-DprojectGroupId=com.monapp \
-DprojectArtifactId=mon-service \
-Dextensions="rest-jackson,hibernate-orm-panache,jdbc-postgresql"
cd mon-service
# Démarrage en mode dev (hot reload)
./mvnw quarkus:dev
Le mode dev de Quarkus inclut un hot reload sans redémarrage (plus rapide que Spring DevTools) et une interface de dev sur http://localhost:8080/q/dev/.
REST avec RESTEasy Reactive
@Path("/api/produits")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ProduitResource {
@Inject
ProduitService produitService;
@GET
public List<ProduitDto> findAll() {
return produitService.findAll();
}
@GET
@Path("/{id}")
public Response findById(@PathParam("id") Long id) {
return produitService.findById(id)
.map(p -> Response.ok(p).build())
.orElse(Response.status(Response.Status.NOT_FOUND).build());
}
@POST
@Transactional
public Response create(@Valid ProduitRequest request) {
ProduitDto created = produitService.create(request);
return Response.created(URI.create("/api/produits/" + created.id()))
.entity(created)
.build();
}
}
L’annotation @Transactional sur la méthode REST est valide en Quarkus (contrairement à Spring où elle doit être sur le service). Les deux styles fonctionnent.
Panache : ORM simplifié
Panache est la couche ORM de Quarkus, construite sur Hibernate. Elle offre deux patterns : Active Record et Repository.
Pattern Active Record : l’entité est aussi le repository.
@Entity
@Table(name = "produits")
public class Produit extends PanacheEntity {
// L'id Long est hérité de PanacheEntity
@Column(nullable = false)
public String nom;
public String description;
@Column(name = "prix_ht")
public BigDecimal prixHT;
public boolean actif = true;
// Méthodes de requête statiques sur l'entité
public static List<Produit> findActifs() {
return list("actif", true);
}
public static Optional<Produit> findByNom(String nom) {
return find("nom", nom).firstResultOptional();
}
public static long countActifs() {
return count("actif", true);
}
}
Utilisation :
// Dans le Resource ou Service
List<Produit> produits = Produit.findActifs();
Produit.persist(nouveauProduit); // INSERT
Produit.deleteById(id); // DELETE
Pattern Repository (plus proche de Spring Data) :
@ApplicationScoped
public class ProduitRepository implements PanacheRepository<Produit> {
public List<Produit> findActifsByCategorie(String categorie) {
return list("actif = true AND categorie = ?1", categorie);
}
public Page<Produit> findPaginated(int page, int size) {
return findAll().page(Page.of(page, size));
}
}
Injection de dépendances : CDI, pas Spring
Quarkus utilise CDI (Contexts and Dependency Injection), le standard Jakarta EE. La différence principale avec Spring :
| Spring | Quarkus (CDI) |
|---|---|
@Service | @ApplicationScoped |
@Component | @ApplicationScoped |
@Autowired | @Inject |
@Value("${prop}") | @ConfigProperty(name = "prop") |
@Configuration | @ApplicationScoped + @Produces |
@ApplicationScoped
public class ProduitService {
@Inject
ProduitRepository repository;
@ConfigProperty(name = "app.produit.max-par-page", defaultValue = "20")
int maxParPage;
public List<ProduitDto> findAll() {
return repository.listAll()
.stream()
.map(this::toDto)
.toList();
}
}
Configuration multi-environnement
# application.properties
quarkus.datasource.db-kind=postgresql
quarkus.datasource.jdbc.url=${DATABASE_URL:jdbc:postgresql://localhost:5432/monapp}
quarkus.datasource.username=${DB_USER:monapp}
quarkus.datasource.password=${DB_PASSWORD:devpassword}
quarkus.hibernate-orm.database.generation=validate
# Config par profil (%dev, %test, %prod)
%dev.quarkus.hibernate-orm.database.generation=drop-and-create
%dev.quarkus.hibernate-orm.log.sql=true
%test.quarkus.datasource.db-kind=h2
%test.quarkus.datasource.jdbc.url=jdbc:h2:mem:test
Build en mode natif
# Prérequis : GraalVM installé (ou Docker)
./mvnw package -Pnative
# Avec Docker (plus simple, pas besoin de GraalVM local)
./mvnw package -Pnative -Dquarkus.native.container-build=true
# L'exécutable généré
./target/mon-service-1.0-runner
# Démarrage en ~50ms, consommation ~30-60MB
Point d’attention : le mode natif a des contraintes. La réflexion Java dynamique doit être déclarée. Les librairies tierces doivent supporter GraalVM (la plupart des extensions Quarkus officielles le font nativement).
Dockerfile pour Quarkus natif
FROM quay.io/quarkus/ubi-quarkus-native-image:22.3-java17 AS build
WORKDIR /code
COPY --chown=quarkus:quarkus mvnw /code/mvnw
COPY --chown=quarkus:quarkus .mvn /code/.mvn
COPY --chown=quarkus:quarkus pom.xml /code/
USER quarkus
RUN ./mvnw dependency:resolve
COPY src /code/src
RUN ./mvnw package -Pnative
FROM quay.io/quarkus/quarkus-micro-image:2.0
WORKDIR /work/
COPY --from=build /code/target/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
Image finale : ~50 MB (vs ~200 MB pour Spring Boot JVM, ~500 MB pour Spring Boot JDK complet).
Quarkus vs Spring Boot : quand choisir ?
Choisir Quarkus :
- Microservices Kubernetes avec scaling agressif
- Serverless (Lambda, Cloud Run, Azure Functions)
- Contraintes mémoire strictes (edge computing, IoT gateway)
- Nouveau projet greenfield avec équipe prête à apprendre
Rester sur Spring Boot :
- Équipe avec expertise Spring déjà en place (coût de migration élevé)
- Applications monolithiques ou modular monolith
- Intégrations nécessitant l’écosystème Spring (Spring Batch, Spring Integration)
- Projets AEM (Spring est l’écosystème standard côté backend AEM)
Conclusion
Quarkus n’est pas un Spring Boot bis. C’est un framework conçu pour une contrainte précise : Java dans les environnements cloud-natifs où le démarrage rapide et la faible empreinte mémoire sont critiques. Sur ces cas d’usage, il surpasse Spring Boot de façon mesurable. Pour les applications d’entreprise classiques, Spring Boot reste le choix dominant.
Amine MEGDICHE
Développeur AEM & Java Full Stack — Freelance depuis 2013