Support OpenAPI 3.1 top-level webhooks (#375) - #377
Merged
jemacineiras merged 7 commits intoJul 23, 2026
Conversation
…able)
OpenAPI 3.1 / JSON Schema 2020-12 allows a schema's `type` to be an array,
e.g. type: ["string", "null"] (the nullable idiom that replaces 3.0's
`nullable: true`, and general unions). ApiTool.getType() read the type via
JsonNode.textValue(), which returns null for an array node and collapsed to
"", so every isObject/isArray/isString/isNumber/isDateTime predicate and
MapperUtil.getSimpleType failed -> the generator silently produced wrong or
empty types for those fields.
- ApiTool.getType: when `type` is an array, resolve to the first non-"null"
entry ("null" only marks the type as nullable). All the isX predicates and
getSimpleType then work unchanged for union/nullable types.
- MapperUtil.processNumber: read the type via ApiTool.getType instead of
schema.get("type").asText(), so array-valued numeric types resolve.
- Add TypeConstants.NULL.
- Add a 3.1.0 regression fixture (testOpenApi31Types) covering ["string",
"null"], ["integer","null"], ["number","null"]+double, int64 and a plain
array, with golden assets.
Bumps version 6.3.2 -> 6.4.0 across the engine, maven and gradle modules.
Non-array `type` handling is unchanged, so existing 3.0 specs are unaffected.
Follow-up 3.1 items (examples array, $ref siblings, webhooks) tracked in sngular#375.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OpenAPI 3.1 adds a top-level `webhooks` object: a map of named Path Item Objects describing out-of-band requests. The generator only iterated `paths`, so webhooks were ignored - no handler interface, no payload models. Add OpenApiUtil.mergeWebhooksIntoPaths, invoked right after parsing in OpenApiGenerator.processFile. Each webhook (keyed by name) is merged into `paths` under a "/"-prefixed key so the existing pipeline generates a handler interface for its operations and the request/response payload models. `paths` is created if the contract has none, and existing `paths` entries are never overwritten. Adds a 3.1.0 webhooks-only regression fixture (testWebhooks) with golden assets (NewPetApi + PetDTO). Stacked on the 6.4.0 array-type work (sngular#376); both are part of the 3.1 support milestone, so the version stays 6.4.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 15 |
| Duplication | 0 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Webhook operations normally omit `tags`, but createOperation requires one (Objects.requireNonNull), so a realistic tag-less webhook crashed with a NullPointerException in the default by-url grouping mode - and was silently skipped in tag-grouping mode. The prior test masked this by giving the webhook explicit tags. mergeWebhooksIntoPaths now defaults each webhook operation's tags to the webhook name when absent/empty, and skips blank keys (guards the pathUrl.split()[1] grouping). The testWebhooks fixture is updated to the realistic tag-less shape to cover this. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
getType: extract array-type resolution into a helper. A genuine multi-type union (e.g. ["string","integer"]) now logs a warning and uses the first concrete type; a "null"-only/empty type array falls back to `object` instead of an empty type string. Adds edge-case regression fixtures: - testOpenApi31Union: union -> String (+warning), ["null"] -> Object - testWebhookPathCollision: webhook name colliding with an existing path is dropped (existing paths take precedence). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jemacineiras
self-requested a review
July 22, 2026 16:34
jemacineiras
previously approved these changes
Jul 22, 2026
Gradle 9.x plugin validation fails the build when a task type is neither @CacheableTask nor @DisableCachingByDefault. OpenApiTask and AsyncApiTask are code generators whose spec-file inputs are not declared as cacheable inputs, so caching is disabled explicitly with a documented reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds OpenAPI 3.1 top-level
webhookssupport — a checklist item of #375.Background
OpenAPI 3.1 adds a top-level
webhooksobject: a map of named Path Item Objects describingout-of-band requests. The generator only iterated
paths, sowebhookswere silently ignored —no handler interface and no payload models were generated.
Change
OpenApiUtil.mergeWebhooksIntoPaths(openApi), invoked right after parsing inOpenApiGenerator.processFile. Each webhook (keyed by name) is merged intopathsunder a"/"-prefixed key, so the existing path pipeline generates a handler interface for itsoperations and the request/response payload models.
pathsis created if the contract hasnone; existing
pathsentries are never overwritten.OpenApiUtil.WEBHOOKSconstant.This reuses the whole existing grouping / path-mapping / model-extraction pipeline rather than
adding a parallel one, keeping the change small.
Tests
New
3.1.0webhooks-only fixturetestWebhooks:generates:
NewPetApi.java— handler interface withPOST /newPet(newPetWebhook) consumingPetDTOmodel/PetDTO.java— the payload modelOpenApiGeneratorTest: Tests run: 46, Failures: 0, Errors: 0;checkstyle:check— 0 violations.Design note / scope
Webhooks are represented as endpoints in a generated handler interface (the common approach for a
webhook receiver), reusing the path pipeline; the primary value is that webhook payload
schemas become models.
$ref'd webhook Path Items (external files) depend on the Path-Item-$refresolution in #372/#374; inline webhook Path Items are covered here. Remaining #375 items
(
examplesarray,$refsiblings) are separate follow-ups.🤖 Generated with Claude Code