Skip to content

fix: set isOverridden from the model's own properties rather than only when unset - #24823

Open
vivekkumarq wants to merge 2 commits into
OpenAPITools:masterfrom
vivekkumarq:java-alloff-isoverridden-order
Open

fix: set isOverridden from the model's own properties rather than only when unset#24823
vivekkumarq wants to merge 2 commits into
OpenAPITools:masterfrom
vivekkumarq:java-alloff-isoverridden-order

Conversation

@vivekkumarq

@vivekkumarq vivekkumarq commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes #24778.

A property inherited through allOf only produced an overriding fluent setter when the parent schema happened to be declared before the child. Moving MyPets above Pet in the reporter's spec drops Cat's setter entirely — the generated class still extends Pet, but the @Override public Cat petType(...) method is gone.

Cause

addVars marked a parent property as overridden only when the flag was still unset:

if (cm != null && cm.allVars == vars && cp.isOverridden == null) {
    cp.isOverridden = true;
}

fromProperty caches CodegenProperty instances in schemaCodegenPropertyCache, so the instance a child model receives for an inherited property is frequently the same object another model already processed. Once any model has set the flag to false, the == null guard no longer applies and the property is never marked as overridden. Which model reaches the cached instance first depends on the order the schemas appear in the document, which is what makes the symptom order-dependent.

Change

Assign the flag from the condition it actually expresses — a property in allVars is overridden when the model did not declare it itself:

if (cm != null && cm.allVars == vars) {
    cp.isOverridden = !varsMap.containsKey(key);
}

varsMap is already built from cm.vars a few lines above for exactly this purpose, so this reuses the information rather than depending on the mutable state of a shared instance.

Test

testOverrideSetterWhenChildIsDeclaredBeforeParent generates from allOf_composition_discriminator_child_first.yaml, which is the reporter's spec with MyPets moved above Pet, and asserts Cat gets the overriding setter. It fails on master and passes with this change.

The existing testForJavaApacheHttpClientOverrideSetter covers the opposite order and still passes, including its assertion that Pet declares petType without @Override — so the parent side is unaffected.

Verification

Full modules/openapi-generator suite: 4952 tests, 0 failures. The single error is KotlinTestUtilsTest.testNormalCompile, which fails identically on unmodified master on my machine because my checkout path contains a space and the Kotlin compiler receives it percent-encoded (/C:/Users/VIVEK%20KUMAR/...). It is unrelated to this change.

No samples needed regenerating: every committed sample keeps its current declaration order, so none of the generated output changes.


Summary by cubic

Fixes inherited allOf properties losing their overriding fluent setter when the child schema is declared before the parent (#24778). The old logic only marked a property as overridden when isOverridden was still null, but fromProperty caches shared CodegenProperty instances, so whichever model was processed first left the flag false. The flag is now derived from whether the model declared the property itself via the existing varsMap.

Adds a regression test using a child-first spec that asserts Cat generates the overriding petType setter. Committed Java samples were regenerated to restore the missing overriding fluent setters; all sample diffs are additions, so only the restored setters change.

Written for commit ba72da8. Summary will update on new commits.

Review in cubic

…y when unset

A property inherited through allOf only produced an overriding fluent setter
when the parent schema happened to be declared before the child. Reordering
the components so the child comes first dropped the setter entirely.

addVars marked a parent property as overridden only when isOverridden was
still null. fromProperty caches CodegenProperty instances in
schemaCodegenPropertyCache, so by the time a child model reached the cached
property, whichever model was processed first had already set the flag to
false and the guard no longer applied. Which model got there first depends on
the order the schemas appear in the document.

Assign the flag from the condition it actually expresses: a property in
allVars is overridden when the model did not declare it itself.

Fixes OpenAPITools#24778

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Re-trigger cubic

The ordering fix restores overriding fluent setters that the affected
samples were missing, all additions.
@vivekkumarq

Copy link
Copy Markdown
Contributor Author

Correcting something I got wrong in the description above: I wrote that no samples needed regenerating. That was an assumption I had not tested, and the Samples up-to-date check disproved it. Samples are now regenerated and pushed.

The regenerated output is worth a look, because it makes the case better than my synthetic spec did:

22 files changed, 372 insertions(+)

Every changed line is an addition — 62 overriding fluent setters that these samples were silently missing, for example in restclient-sealedInterface:

+  @Override
+  public BarRef name(@jakarta.annotation.Nullable String name) {
+    this.setName(name);
+    return this;
+  }

So this is not only reachable through a deliberately reordered document: sealedInterface and several petstore Java clients are committed in the repository today with those setters absent. The oneOf wrapper in those specs is resolved before the parent, which is the same ordering the issue describes.

Scope of the regeneration: isOverridden is referenced by five templates, all under Java/ (pojo.mustache plus the webclient, resttemplate, restclient and native libraries), so only the Java client generator can produce different output. I regenerated all 101 configs with generatorName: java rather than only the ones CI flagged, to be sure nothing else moved.

Unchanged from before: full modules/openapi-generator suite is 4952 tests with 0 failures, and the existing testForJavaApacheHttpClientOverrideSetter still passes, including its assertion that Pet declares petType without @Override.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] [Java] Fluent builder through allOf is lost if the child is read before the parent

1 participant