Avant de plonger dans les internals, fixer le vocabulaire. Les termes ci-dessous sont ceux de la spec Jakarta Servlet 6.1 tels qu’implémentés par Foy.

Vocabulaire de base

Terme Définition côté Foy

Request / Response

HttpServletRequest / HttpServletResponse. Implémentés par HttpServletRequestImpl / HttpServletResponseImpl qui adaptent les Request / Response de Chappe sans copie de body.

Servlet

Un jakarta.servlet.Servlet (typiquement un HttpServlet) qui répond à un mapping d’URL. Découvert par @WebServlet ou par <servlet> dans web.xml.

Filter chain

Pipeline de jakarta.servlet.Filter traversé avant la Servlet cible. Construit par FilterRegistry à partir des <filter-mapping> et @WebFilter. Ordre déterministe (voir Référence).

Listener

Un bean qui réagit au cycle de vie du container (ServletContextListener), des sessions (HttpSessionListener), ou des requêtes (ServletRequestListener). Enrôlé par ListenerRegistry à partir de @WebListener.

ServletContext

Implémenté par VidocqServletContext. Un par contextPath. Porte les attributs partagés, les beans CDI exposés, les RequestDispatcher.

RequestDispatcher

Mécanisme forward / include. Implémenté par RequestDispatcherImpl qui réutilise le routage Chappe.

Async

request.startAsync() retourne un AsyncContext. Aucun pool plateforme à protéger : chaque requête tourne sur un virtual thread, l’async sert juste à découpler la réponse de la requête côté programme.

Multipart

@MultipartConfig + request.getParts(). Parsing en streaming sur le body Chappe.

Métaphore : la couche au-dessus du transport

Chappe bouge des octets : il sait répondre à HTTP/1.1 ou HTTP/2 sur TLS, gérer une connexion, lire un body. Il ne sait pas ce qu’est une « Servlet » ou un « filtre ».

Foy interprète ces octets : il transforme une connexion HTTP en HttpServletRequest, retrouve la Servlet associée à l’URL, déroule la chaîne de filtres, écrit la réponse. C’est exactement la division que faisait l’administration télégraphique du XIXᵉ siècle entre les stationnaires (qui relayaient le code Chappe sans le comprendre) et les directeurs de bureau (qui interprétaient le message).

Découverte d’application

foy-core orchestre la fusion entre annotations et descripteurs :

  1. lecture des annotations (@WebServlet, @WebFilter, @WebListener, @MultipartConfig) — résolues à la compilation par un APT, exposées via le BeanManager Vauban ;

  2. lecture des descripteurs (WEB-INF/web.xml, META-INF/web-fragment.xml) via WebXmlParser qui produit un WebAppDescriptor ;

  3. fusion selon metadata-complete (standard Servlet 6.1) ;

  4. WebAppDiscovery réalise cette agrégation au démarrage de FoyChappeBoot.

Aucun scan classpath runtime. Tous les beans Servlet sont déjà connus de Vauban à la compilation.

Pont Chappe ↔ Servlet

foy-chappe héberge ChappeServletBridge, un Handler Chappe qui :

  1. expose Request Chappe comme HttpServletRequestImpl ;

  2. expose Response Chappe comme HttpServletResponseImpl ;

  3. invoque la chaîne FilterServlet ;

  4. retourne le Body Chappe construit autour de ServletOutputStreamImpl.

L'`OutputStream` Servlet est branché directement sur le streaming Chappe — pas de copie de body, pas de buffer intermédiaire.

Sécurité applicative

  • BasicAuthenticator — Basic Auth standard (RFC 7617).

  • SecurityConstraintEnforcer — applique les <security-constraint> du web.xml.

  • AnonymousSecurityProvider — fallback ouvert pour le développement.

  • SPI publique : io.vidocq.foy.spi.security.SecurityProvider permet de greffer un provider custom (LDAP, JWT, OIDC).

Form-based et Digest : // TODO@user: documenter une fois stables. Jakarta Authentication / Authorization : // TODO@user: planifié, jalon ultérieur.

CDI : un BeanManager unique

foy-cdi-vauban greffe la Servlet API sur Vauban :

  • le ServletContext est exposé en @ApplicationScoped ;

  • HttpServletRequest en @RequestScoped ;

  • HttpSession en @SessionScoped (// TODO@user: confirmer disponibilité M2) ;

  • les Servlet/Filter peuvent porter @Inject.

Toute la résolution se fait à la compilation par Vauban — aucun proxy dynamique, aucune réflexion à chaud, compatible AOT (GraalVM, Leyden CDS).

Différences Servlet 6.1 vs 5.0

Aspect Servlet 5.0 (Jakarta EE 9.1) Servlet 6.1 (Jakarta EE 11)

Package

jakarta.servlet.* (rebrand)

jakarta.servlet.* (stable)

Modules JPMS

Optionnel

Recommandé — Foy l’impose

Threading I/O

Pool plateforme + NIO Selector

Virtual threads (Foy : un VT par requête)

API legacy

SingleThreadModel, <run-as> partiel

Supprimés / clarifiés

WebSocket

Spec séparée 2.1

Spec séparée 2.2 — // TODO@user: à implémenter

HTTP/3

Hors scope

Hors scope (côté transport — voir Chappe)

Foy se concentre sur le sous-ensemble pertinent en 2026 : pas de JSP, pas de SCI runtime via META-INF/services, pas de réflexion. Les libs qui en dépendaient sont à porter via une SPI explicite ou un APT.