This page defines the JAX-RS vocabulary as Cassini implements it, and clarifies what Jakarta REST 4.0 brings over JAX-RS 3.x — strict JPMS, SeBootstrap, virtual threads.
JAX-RS vocabulary
Resource |
Class annotated |
Resource method |
Method annotated with an HTTP verb — |
Provider |
|
Filter |
|
Interceptor |
|
Application |
|
ParamConverter |
|
Cassini stack and transports
Cassini cleanly separates the REST layer (annotation parsing, dispatch, content negotiation) from the HTTP transport:
-
cassini-api— public SPI (CassiniHttpExchange,CassiniHttpAdapter,CassiniStack,BeanProvider,ResourceFactory). Zero internal symbol, zero transport dependency. -
cassini-core— JAX-RS engine (Invoker, ResourceScanner, MessageBodyRegistry). Strict-spec, transport-agnostic. -
cassini-chappe— wires the engine onto Chappe (HTTP/1.1, H2, virtual threads). TCK reference transport. -
cassini-jdk-http— JDK 25com.sun.net.httpserverfallback (zero external dependency, ideal for smoke tests). -
cassini-cdi-vauban—BeanProvideradapter that resolves resources through Vauban. -
cassini-client— zero-dependency JAX-RSClientBuilderonjava.net.http+ virtual threads (server-independent).
CassiniStack.builder() picks the transport via ServiceLoader — application code references no transport-specific symbol.
Two resource instantiation modes
-
Mode A — without CDI:
new()viaResourceFactory.defaultFactory(). Used bycassini-jdk-httpstandalone and demos. Resources are@Singletonor per-request depending on declared scope. -
Mode B — DI via
BeanProviderSPI:cassini-cdi-vaubanor any otherServiceLoaderadapter. Nojakarta.cdiimport incassini-api/cassini-core— strict decoupling.
Routing: Cassini’s map
Like geodetic triangulation, JAX-RS routing is hierarchical and deterministic:
-
Literal match has priority over regex match (
{id}then\{id:\\d+}). -
Best-match on the (path, verb, media-type) triple —
Request.selectVariantserver-side,@Produces/@Consumesannotation-side. -
Sub-resource locator: the method returns an instance, its
@Pathis consumed, dispatch resumes from that instance.
REST 4.0 vs 3.x differences
JAX-RS 3.x |
Jakarta REST 4.0 (Cassini) |
Implicit transport (Servlet 4) |
Native |
Platform threads |
Virtual threads by default (Java 25), no platform pool needed |
No official module-info support |
Native JPMS: complete |
Bootstrap limited to container |
Standalone |
Partial multipart (Forms) |
First-class |
Partial records |
Java 17+ records natively supported on the binding side (Champollion) |
Static codegen
Cassini favours compile-time generation over runtime reflection. Per @Path class it generates two name-looked-up artefacts:
-
<ResourceClass>$$CassiniAdapter— direct method invocation + field injection + inline@*Paramcoercion (noMethod.invoke, no per-request reflection). -
<ResourceClass>$$CassiniRoutes— the route table as literals, converted to routes at startup without an annotation scan.
Three tiers produce these, most-preferred first: APT (cassini-processor, compile time), the Maven plugin (cassini-maven-plugin, build time, for dependency JARs), and a runtime Class-File API generator (JVM-only fallback). The first two are AOT-compatible (GraalVM, Leyden CDS). MessageBodyReader/Writer providers register via META-INF/services; filter @Priority ordering is resolved at stack build, not per request.
See internals for the full pipeline and the documented residual reflection.
TCK scope: Core Profile / SE-Bootstrap
Cassini targets the Core Profile / SE-Bootstrap target: no Servlet on the server side, no JAXB-runtime. The TCK tags servlet and xml_binding are excluded per TCK Process 1.4.1 §5.2.3. Details in TCK.