Knock repose sur un principe simple : implémenter MicroProfile Health 4.0 avec le seul JDK et les specs Jakarta. Aucune bibliothèque tierce, aucune mécanique lourde en réflexion, aucun pool de threads plateforme. Cette page documente les choix d’implémentation qui maintiennent cette discipline.
Architecture des modules
| Module | Responsabilité |
|---|---|
|
Fork Vidocq de l’API MicroProfile Health, reconditionné avec un |
|
SPI Knock : |
|
Runtime autonome : registre, agrégateur, sérialiseur JSON-P, constructeur de réponse, façade |
|
Build Compatible Extension CDI + auto-enregistrement sur Vauban. |
|
Ressource Jakarta REST exposant |
|
Lanceur du TCK officiel MicroProfile Health 4.0. |
Flux d’exécution
-
HealthCheckRegistry.getChecks(ProbeType)renvoie les contrôles de la sonde demandée. -
Chaque
HealthCheck.call()s’exécute sur son propre thread virtuel. -
KnockAggregatorréduit les réponses en unHealthSnapshot(règles spec §3.2). -
KnockJsonSerializerrend l’instantané via Jakarta JSON-P. -
KnockHealthServiceencapsule le résultat dans unHealthReport(statut HTTP + charge utile).
Classes du cœur
| Classe | Rôle |
|---|---|
|
Implémentation de |
|
Applique la règle d’agrégation §3.2 et replie les exceptions en contrôles |
|
Construit la réponse avec Jakarta JSON-P ( |
|
Implémentation de |
|
Implémentation de la SPI |
|
Résultat d’agrégation immuable : type de sonde, statut global, liste de contrôles. |
|
Façade publique liant registre + agrégateur + sérialiseur. |
|
Enveloppe de réponse HTTP : code de statut + JSON sérialisé. |
Découverte CDI
knock-cdi-vauban fournit deux pièces internes :
-
HealthCheckCdiExtension— une Build Compatible Extension validant la règle du qualificateur de sonde unique au moment du build (spec §4.2) ; -
HealthCheckRegistrar— un bean CDI qui, sur@Initialized(ApplicationScoped.class), enregistre chaqueHealthCheckdécouvert dans le registre (spec §4.1).
La découverte utilise le pipeline BCE de Vauban — pas de balayage du classpath à l’exécution, pas de setAccessible(true).
Ressource JAX-RS
KnockHealthResource est annotée @Path("/health") et expose les quatre endpoints. Chaque méthode associe son chemin à un ProbeType, appelle KnockHealthService.report(…) et renvoie une Response avec le statut HTTP de l’instantané. La ressource n’importe que jakarta.ws.rs — jamais un paquet interne de Cassini.
Modèle de threads
Toute l’exécution des contrôles passe par Executors.newVirtualThreadPerTaskExecutor() (JEP 444). Conséquences :
-
un contrôle lent ne bloque jamais le reste d’un groupe de sondes ;
-
pas de pool de threads plateforme, pas de file bornée, pas de
ThreadLocal; -
l’état partagé (le registre) utilise exclusivement
ConcurrentHashMap.
Contournement JPMS (ADR-001)
Le jar amont de l’API MicroProfile Health est livré sans module-info.class, ce qui casse le JPMS strict et jlink. Knock le fork sous knock-mp-health-api et le reconstruit avec un descripteur de module en bonne et due forme. Pour empêcher ce descripteur d’interférer avec le traitement des annotations, le module-info.java réside dans src/main/module-info/ et est compilé dans une phase dédiée à prepare-package. La SPI est enregistrée deux fois — via provides JPMS et META-INF/services — afin que l’implémentation se résolve sur le module path comme sur le classpath. Justification complète : docs/adr/ADR-001-jpms-workaround-microprofile-health.md.
Compatibilité AOT
Pas de génération de proxy dynamique, pas de setAccessible(true), pas de réflexion à chaud dans le chemin de requête. Knock est compatible native-image et fonctionne dans une image jlink minimale.
Sources
-
knock-core — registre, agrégateur, sérialiseur, façade.
-
knock-cdi-vauban — découverte CDI.
-
knock-jaxrs — endpoints REST.
-
ADR-001 — contournement JPMS.