Request sequence
No body copy: ServletOutputStreamImpl writes straight into the Chappe Body. The ServletInputStream reads straight from the Chappe frame parser.
Threading model
-
One virtual thread per request. Chappe’s
accept()already produces one VT per connection. Foy stays on that thread untilservice()returns. -
No platform pool. No
ExecutorServiceto size. -
Async: no extra cost.
request.startAsync()captures the current VT; the program may detach the response, but the container reserves no platform thread. -
ThreadLocalis used sparingly throughScopedValue(JEP 506) on the Chappe side. Foy inherits that context without pinning.
|
The bridge never |
Container lifecycle
fireContextInitialized() and fireContextDestroyed() are exposed by FoyChappeBoot.Mounted — the caller picks the exact moment (typically right after mount / right before unmount).
CDI integration through Vauban
foy-cdi-vauban works in two phases:
-
build-time (Vauban) — Vauban’s annotation processor generates bean producers for
ServletContext,HttpServletRequestandHttpSession. No reflection, allClass-File API(JEP 484). -
runtime (Foy) —
FoyVaubanBootstrap.beanManager()returns theBeanManagerinjected intoFoyChappeBoot. On every request,ServletDispatcherpushes the currentHttpServletRequestinstance into theRequestScopedcontext.
Benefit: @Inject HttpServletRequest req works in any Servlet or Filter, with no runtime dynamic proxy.
Implementation choices
| Choice | Justification |
|---|---|
No runtime classpath scan |
All |
No runtime reflection |
Aligns with the Vidocq ecosystem’s principles. AOT-friendly (GraalVM, Leyden CDS). |
No body copy |
|
|
Temporary M1 coupling — to be replaced in M2 by a |
No runtime |
Servlet SPIs (e.g. |
Known limits
-
Cross-context dispatch (
ServletContext.getContext): not implemented — see TCK: Jakarta Servlet 6.1. -
WebSocket Servlet 6.1:
// TODO@user: planned, no date. -
JSP: not supported, not planned.
-
Form-based authentication:
// TODO@user: in progress.
For comparative numbers (Tomcat, Jetty), see BENCH.md.