micronaut-projects / micronaut-projects/micronaut-openapi
micronaut-openapi 5.0.2 / openapi-generator 7.0.0: broken oneOf + discriminator codegen for allOf-composed branches
- Dominant language
- Java
- Stars
- 114
- Forks
- 121
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 25
Description
### Expected Behavior
## Summary
When a `oneOf` schema with a `discriminator.mapping` has branches that are themselves
`allOf`-composed (a common pattern for "base envelope + specific payload"), the generator
fails to resolve the discriminator mapping targets by name, silently falls back to synthetic
`OneOf` / `OneOf1` model names for the branches — but the generated
`@JsonSubTypes` annotation on the parent interface still references the **original, unresolved**
branch names, which are never generated. The result does not compile.
This reproduces with `io.micronaut.openapi` Gradle plugin `5.0.2` (which pulls in
`io.micronaut.openapi:micronaut-openapi-generator:7.0.0`). It does **not** reproduce with
`io.micronaut.openapi` `4.6.1` (`micronaut-openapi-generator:6.12.2`), which generates the
expected `StatusEvent` / `ErrorEvent` class names.
## Reproduction
This is a fully standalone Gradle project. (see the attached tar.gz)
```bash
./gradlew generateEventsOpenApiModels
```
### Input
Two files under `src/main/resources/contracts/`:
- `events-api.json` — a minimal OpenAPI 3.1.1 document with one endpoint whose request body
is `$ref`'d from an external JSON-Schema file.
- `event-defs.json` — a JSON-Schema (draft-07 style) file defining:
- `BaseEvent` — a plain object schema (envelope fields).
- `StatusEvent`, `ErrorEvent` — each `allOf: [{"$ref": "#/definitions/BaseEvent"}]` plus their
own `properties` (this is the "envelope + payload" composition pattern).
- `DomainEvents` — `oneOf: [StatusEvent, ErrorEvent]` with a `discriminator.mapping` keyed by
a `type` constant, pointing at the two schemas above by `$ref`.
### Observed output
```
Failed to lookup the schema 'StatusEvent' when processing the discriminator mapping of oneOf/anyOf. Please check to ensure it's defined properly.
Failed to lookup the schema 'ErrorEvent' when processing the discriminator mapping of oneOf/anyOf. Please check to ensure it's defined properly.
```
Generated files under `build/generated/openapi/generateEventsOpenApiModels/.../dto/`:
- `DomainEventsOneOf.java` (should be `StatusEvent.java`)
- `DomainEventsOneOf1.java` (should be `ErrorEvent.java`)
- `DomainEvents.java` — the discriminator interface, which still contains:
```java
@JsonSubTypes({
@JsonSubTypes.Type(value = ErrorEvent.class, name = "com.example.event.Error"),
@JsonSubTypes.Type(value = StatusEvent.class, name = "com.example.event.Status"),
})
public interface DomainEvents {
```
`ErrorEvent` and `StatusEvent` are never generated (only `DomainEventsOneOf`/`DomainEventsOneOf1`
are), so this interface fails to compile with `cannot find symbol`.
### Expected output
`StatusEvent.java` and `ErrorEvent.java` should be generated directly (as they are with the
4.6.1 / 6.12.2 generator pair), and the `@JsonSubTypes` annotation on `DomainEvents` should
reference those same generated classes.
## Workaround attempted
Setting `modelNameMapping` in the `openapi { server(...) { ... } }` DSL block
(`modelNameMapping.put("DomainEventsOneOf", "StatusEvent")`) had no effect on the generated
output — the synthetic names and the broken `@JsonSubTypes` reference are unchanged.
[bugreport-micronaut-openapi-oneof-discriminator.tar.gz](https://github.com/user-attachments/files/31215173/bugreport-micronaut-openapi-oneof-discriminator.tar.gz)
### Actual Behaviour
_No response_
### Steps To Reproduce
_No response_
### Environment Information
- `io.micronaut.library` / `io.micronaut.openapi` Gradle plugin: `5.0.2`
- `io.micronaut.openapi:micronaut-openapi-generator`: `7.0.0` (transitively resolved)
- Gradle: 9.7.0
- JDK: 21 (also reproduces on 25)
### Example Application
_No response_
### Version
5.0.2
Contributor guide
No contributing guide indexed for this repository
Research direction
Run ./gradlew generateEventsOpenApiModels in the attached standalone project and inspect src/main/resources/contracts/events-api.json and event-defs.json. Compare the generated DomainEventsOneOf.java, DomainEventsOneOf1.java, and DomainEvents.java with the output from the 4.6.1/6.12.2 generator pair. Done means StatusEvent.java and ErrorEvent.java are generated and DomainEvents references those same classes in @JsonSubTypes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, openapi
- Domain
- api, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 56/100