OpenAPITools / OpenAPITools/openapi-generator
[BUG][JAVA][Spring] Required child attributes that override optional parent attributes are ignored by validation and required args constructors
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator?
- Have you tested with the latest master to confirm the issue still exists?
- Have you searched for related issues/PRs?
- What's the actual output vs expected output?
- [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
With REF_AS_PARENT_IN_ALLOF=true, when a child type inherits an optional attribute and overrides it as required, the child type's required args constructor ignores that optional attribute.
For example, the following class is generated for the parent type, with the single required property accepted in the required args constructor:
public class ParentType {
private @Nullable String optionalProp;
private String requiredProp;
public ParentType() {
super();
}
/**
* Constructor with only required parameters
*/
public ParentType(String requiredProp) {
this.requiredProp = requiredProp;
}
@Schema(name = "optionalProp", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@JsonProperty("optionalProp")
public @Nullable String getOptionalProp() {
return optionalProp;
}
// ...
@NotNull
@Schema(name = "requiredProp", requiredMode = Schema.RequiredMode.REQUIRED)
@JsonProperty("requiredProp")
public String getRequiredProp() {
return requiredProp;
}
// ...
}
When a child type inherits from ParentType and marks the inherited optionalProp as required, the following is generated:
public class ChildType extends ParentType {
public ChildType() {
super();
}
/**
* Constructor with only required parameters
*/
public ChildType(String optionalProp, String requiredProp) { // <-- `optionalProp` is ignored!
super(requiredProp);
}
// ... no overridden getter for `optionalProp` with `@NotNull`
}
Note how the child's constructor accepts but then ignores the optionalProp attribute.
Also, @NotNull should be added to an overridden getter to enforce that the attribute is required in this child type.
One workaround to avoid accidental use of the constructor is to disable the generation of the required args constructor with -p generatedConstructorWithRequiredArgs=false (e.g. by Jackson, which as of Jackson 3 uses that constructor, resulting in optionalProp values from incoming JSON not to be bound).
Apart from refactoring the spec, I haven't found a workaround to have the correct validation annotations to be generated on the child type.
openapi-generator version
7.18.0, 7.19.0-SNAPSHOT
OpenAPI declaration file content or url
openapi: 3.0.3
info:
title: Title
version: "1"
paths:
/test:
get:
responses:
"200":
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/ChildType'
components:
schemas:
ParentType:
type: object
properties:
optionalProp:
type: string
requiredProp:
type: string
required:
- requiredProp
ChildType:
allOf:
- $ref: '#/components/schemas/ParentType'
- type: object
required:
- optionalProp
Generation Details
java -jar openapi-generator-cli-7.19.0-SNAPSHOT.jar generate -g spring -i spec.yaml -o out --openapi-normalizer REF_AS_PARENT_IN_ALLOF=true
Suggest a Fix
The required args constructor of the child should set the affected attribute itself, and the child should override the parent's getter and add @NotNull.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue with the provided OpenAPI declaration and the Spring generation command using REF_AS_PARENT_IN_ALLOF=true. Inspect the generated ParentType and ChildType constructors, inherited properties, and validation annotations. The issue is done when ChildType passes the required inherited value to its parent and overrides the getter with @NotNull so validation and JSON binding work correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- backend-api-design, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100