New in the 0.4.0-SNAPSHOT development line — everything listed here landed after the 0.3.0 release and is not part of it. Every entry links to the section that documents it, and those sections carry the NEW badge. Each brick of the suite keeps its own page of this kind; the ecosystem index gathers them. When the next release train ships, this page is frozen with it and restarts empty on the dev line.
MicroProfile OpenAPI 4.2
Grimm targets the MicroProfile OpenAPI 4.2 API. The build pins 4.2-RC5 until the final reaches Maven Central, and the official TCK 4.2-RC5 passes at 367 / 367; the run will be repeated on the final. TCK.
-
Unknown
Schemaproperties are extensions — aSchemakeeps any property it does not know,x-prefixed or not, and writes it back.getAll()lists every property set, under its JSON name, andsetAll(…)clears them all first, as the 4.2 Javadoc says; in 0.3.0, both saw only the unknown properties. Static documents and schema overrides. -
@Headerexampleandexamples— mapped onto the header, from annotations and from a static file. Supported annotations. -
@ExternalDocumentationon a resource method — becomes the operation’sexternalDocs. Supported annotations. -
multipleOfandpatternfrom@Digits— Bean Validation@Digitsgives amultipleOfon anumberschema and apatternon astringschema, never overriding a value set on the schema. Decimals are written as plain decimals (0.0000000001, not1E-10), which a YAML 1.1 parser still reads as numbers. How annotation values are mapped.
How the model sources combine
-
The static file now wins over the
OASModelReader— behaviour change. The specification’s processing rules start from the reader model, apply the static file on top of it, then the annotations, then theOASFilter. Up to 0.3.0, Grimm merged the static file first and the reader over it, so on a conflict the reader won. If your reader was meant to overrideMETA-INF/openapi.yaml, move that override to an annotation or a filter. How the sources combine, Upgrading from 0.3.0. -
Schemas at the same position merge keyword by keyword — when two sources describe the schema of a media type, a property or
items, every keyword of the higher-priority source now wins (minimum,pattern,readOnly,examples,not, …); only a handful were copied before. Its explicit empty values (default: [],const: {},x-tags: []) are kept too. A named component schema is still taken whole. How the sources combine. -
A
summarybeside a$refis lost — OpenAPI 3.1 allows it on a Reference Object, but the MicroProfile OpenAPI model has nosummaryon a parameter, request body, response, header, link, security scheme or callback, so a static file that writes one loses it. This is a limitation of the API, documented rather than worked around. How the sources combine.
A more faithful document
A review of the 4.2 work found the places where Grimm dropped or bent what the application wrote. All are fixed, each with its own test; the TCK does not exercise these cases.
-
@Schemaand@SchemaPropertymap every attribute —@SchemaPropertyused to map a dozen attributes; both annotations now share one mapping that covers bounds, lengths, counts, flags, composition, the discriminator,externalDocswith its extensions,examplesand the JSON Schema 2020-12 keywords. How annotation values are mapped. -
No more stray
minItems,maxItems,maxProperties— every annotated schema used to carryminItems: 2147483647,maxItems: -2147483648andmaxProperties: 0. An attribute left at its default now writes nothing. How annotation values are mapped. -
A partial
@Schemais applied — on a parameter, request body, header or content entry, a@Schemathat sets onlyminimum,examples,oneOf,readOnly, … was ignored in favour of the inferred schema. It is now applied. How annotation values are mapped. -
constValue,examplesand parsed extension values are JSON —constValueandexamplesare parsed as JSON unless the schema type isSTRING, and@Extension(parseValue = true)values go through the strict JSON reader of static files instead of a lossy hand-written one. Behaviour change: lenient values that are not JSON ({a: 1},TRUE,1L) stay strings. How annotation values are mapped, Upgrading from 0.3.0. -
Static-file keywords keep their type —
minimum,maxLength,not,discriminator,xml,externalDocs, … read from a static file (or from anmp.openapi.schema.<FQCN>value, or a processor fragment) were stored as extensions, so anOASFilterclearing extensions wiped them; they are typed properties now. Static documents and schema overrides. -
Static-file
$refand fields are kept — the$refof a parameter, request body, response or callback is kept as written, as are parameter and header fields (style,explode,content,example,examples, …), discriminatorx-keys,type: "null"and YAML 1.2 numbers. Static documents and schema overrides. -
mp.openapi.schema.<FQCN>reads every keyword — the value goes through the static-file mapper instead of a converter that knew a few keywords; therefalias works at every level,$defsanddefinitionsincluded. Behaviour change: an explicit$refis kept verbatim, so a short name there needsrefor the full#/components/schemas/…. Static documents and schema overrides. -
Bean Validation on a parameter reaches the document — the annotation processor built a parameter schema from its type alone, so a compile-time fragment lacked the constraints the runtime scan derives. Such a class is now left to the runtime scan. Build pipeline.
Java modules
-
Grimm ships named modules — the
module-infoofgrimm-core,grimm-processorandgrimm-cdi-vaubanwas never compiled into the jars, so Grimm ran as automatic modules. In a modular application, a build tool could then takegrimm-cdi-vaubanfor a class-path jar and split its package, and/openapianswered 404 (grimm#15). Each jar now carries its descriptor:grimm-cdi-vaubanrequires transitivethe MicroProfile OpenAPI and JAX-RS APIs its own API exposes andprovidesits generated_VaubanComponents, so the container builds its beans with noopens. Amodule-info.javathat saidrequires grimm.cdi.vauban;now saysrequires io.vidocq.grimm.cdi.vauban;. Java modules, Upgrading from 0.3.0. -
The annotation processor resolves as a module —
grimm-coreexports the two packages the processor uses (io.vidocq.grimm.internal,io.vidocq.grimm.internal.schema) toio.vidocq.grimm.processoras well, still as qualified exports, so the processor works from the module path (grimm#19). Java modules.
Other CDI containers
-
Proven on Weld and Open Liberty — two new test modules run the Grimm jars, unchanged, without Vauban:
grimm-it-weldon Weld SE 6.0 (class path, plus two containers in one JVM) andgrimm-it-openlibertyas a WAR on Open Liberty 26.0.0.10 (MicroProfile 7, CDI 4.0) with Liberty’s ownmpOpenAPIoff. Neither is published (grimm#22). Other CDI containers. -
vauban-apiis now a runtime dependency ofgrimm-cdi-vauban— it wasprovided, so outside Vauban the model cache, the/openapiresource and the auto-discovery bean could not be loaded (BUG-20261010-01). It no longer brings the CDI API. Other CDI containers. -
Two containers keep their documents apart — the class names the extension records used to live in a
staticset, cleared at each container start: two applications starting together on one server could document each other’s resources (BUG-20261010-02). They now belong to each container, through a syntheticScannedTypesbean. Internals. -
Resources that are not CDI beans are documented — in
annotateddiscovery mode, the resourcesgrimm-processordescribed now enter the document even when the CDI scan never saw them. Other CDI containers. -
Jakarta REST is
providedingrimm-cdi-vauban, and compile scope ingrimm-processor— the runtime jar no longer ships the API (vidocq-workspace#17); this is a behaviour change for an application that compiled against Jakarta REST through Grimm alone. The processor now carries it, so anannotationProcessorPathsentry forgrimm-processorworks on its own. On the Vidocq runtime, the OpenAPI extension brings Jakarta REST. Other CDI containers.