Cyrano est l’implémentation MicroProfile Rest Client 4.0 de l’écosystème Vidocq. Elle transforme une simple interface Java annotée (@Path, @GET, @RegisterRestClient) en un proxy typé qui parle HTTP à votre place : la requête, les paramètres, les headers, la sérialisation JSON-B et la désérialisation typée sont assurés depuis l’ombre, sans réflexion dynamique, sans librairie tierce, et sur des virtual threads natifs du JDK 25.

Origine du nom

Le personnage de Cyrano de Bergerac — du dramaturge Edmond Rostand (1897), inspiré du libre penseur français Savinien de Cyrano de Bergerac (1619-1655) — prête à Christian son éloquence, ses vers, ses sentiments, depuis l’ombre du balcon. Christian n’a qu’à articuler ; le verbe, la cadence, la métaphore viennent de Cyrano. Voir la pièce sur Wikipédia.

Un client REST typé fait exactement le même geste : le code applicatif appelle users.findById(42) et Cyrano parle HTTP en son nom — construit la requête, sérialise le corps, dépose les headers, interprète la réponse, désérialise le type de retour. L’application n’entend que la voix typée ; tout le protocole reste dans l’ombre.

Cyrano, l’éloquent Cyrano, le runtime Rest Client

Discours pour Christian sous le balcon

Appel HTTP au nom du code applicatif

Vers en cadence (rythme, rime)

Requête HTTP formée (méthode, path, headers, body)

Voix portée mais visage caché

Interface typée — le service distant est invisible

Métaphore prêtée, image qui circule

Proxy généré au build-time qui circule via DI

Cadre du langage : alexandrin imposé

Cadre de la spec : @Path, @GET, @RegisterRestClient

Réponse de Roxane interprétée

Réponse HTTP désérialisée typée

En un coup d’œil

Spec implémentée

MicroProfile Rest Client 4.0

Repo

Vidocq/cyrano (miroirs : GitHub, Forgejo)

Java

25 (LTS)

Modules JPMS

io.vidocq.cyrano.mp.rest.client.api, io.vidocq.cyrano.api, io.vidocq.cyrano.core, io.vidocq.cyrano.cdi.vauban

Dépendances runtime

microprofile-rest-client-api (repackagée), jakarta.ws.rs-api, jakarta.json.bind-api (impl runtime : Champollion)

Transport HTTP

java.net.http.HttpClient (JDK pur, HTTP/1.1 + H/2, virtual threads)

Génération de proxy

Class-File API (JEP 484) à la première utilisation — classes nommées Cyrano$<Interface>, pas de java.lang.reflect.Proxy

Intégration CDI

cyrano-cdi-vauban — BCE @Enhancement sur @RegisterRestClient, @Synthesis produit le bean qualifié @RestClient

Prête pour jlink

✅ (le repackage cyrano-mp-rest-client-api neutralise le module automatique upstream)

TCK MicroProfile Rest Client 4.0

140 / 168 (~83 %) hors SSL / timeouts / SSE — voir état TCK

Licence

EPL-2.0 OR EUPL-1.2 OR GPL-2.0-or-later

Trois traits identitaires

  1. Zéro librairie tierce. Aucune dépendance d’implémentation : pas de RESTEasy Client, pas de Jersey, pas de CXF, pas d’OkHttp, pas de Jackson, pas d’ASM, pas de Byte Buddy. Seules les specs Jakarta EE et MicroProfile sont en compile/provided. La couche transport est java.net.http.HttpClient du JDK ; la couche JSON est Jakarta JSON-B (l’implémentation Champollion est fournie au runtime).

  2. Transport JDK natif virtual threads. HttpClient est construit avec Executors.newVirtualThreadPerTaskExecutor(). Chaque appel bloquant occupe un virtual thread, pas un thread plateforme. Aucun synchronized, aucun ThreadLocal dans le chemin chaud — virtual-thread-friendly de bout en bout. Le mode asynchrone (CompletionStage<T>) délègue à HttpClient.sendAsync.

  3. Proxy d’interface généré au build-time, pas à la réflexion. Cyrano ne fait pas java.lang.reflect.Proxy.newProxyInstance(…​). À la première utilisation d’une interface client, le CyranoProxyGenerator émet une vraie classe nommée Cyrano$<SimpleName> via la Class-File API (JEP 484) et la charge avec MethodHandles.Lookup.defineClass. Avantages : stack traces lisibles, pas de setAccessible(true), compatible AOT (GraalVM native-image, Leyden CDS). Le bytecode est mémoïsé par CyranoProxyCache.

Positionnement dans l’écosystème

Diagram

Cyrano se branche en tant que côté client sur le même empilement que Cassini côté serveur : Vauban découvre les @RegisterRestClient et produit les beans synthétiques, Ravel résout les clés <configKey>/mp-rest/url, Champollion sérialise/désérialise les corps JSON. Le transport est java.net.http.HttpClient (JDK), pas Chappe — Chappe est un serveur, pas un client.

Statut courant

L’implémentation core (cyrano-core) et l’intégration CDI (cyrano-cdi-vauban) sont en place. Le TCK MicroProfile Rest Client 4.0 atteint 140 / 168 sur la suite officielle (hors SSL, timeouts longue durée et SSE), soit environ 83 %. L’intégration dans le runtime Vidocq passe par le wrapper vidocq-mps-cyrano-extension (en cours).

Ressources rapides

  • Démarrage rapide — premier appel typé en moins de cinquante lignes.

  • Concepts — vocabulaire MP Rest Client (@RegisterRestClient, RestClientBuilder, qualifier @RestClient, providers).

  • Cas d’usage — paramètres, headers, async, exception mappers, builder programmatique.

  • Référence — coordonnées Maven, modules JPMS, clés MP Config supportées.

  • Fonctionnement interne — scan d’interface, génération de proxy via Class-File API, transport, intégration BCE Vauban.

  • TCK — score officiel, périmètre testé, challenges déclarés.

  • Migration — depuis SmallRye Rest Client / RESTEasy Client.

Licence

EPL-2.0 OR EUPL-1.2 OR GPL-2.0-or-later — voir LICENSE.