Skip to content

fix(java): don't emit unqualified enum default for discriminator ref-to-property - #24934

Open
seonwooj0810 wants to merge 1 commit into
OpenAPITools:masterfrom
seonwooj0810:fix/issue-24874-discriminator-property-ref-enum-default
Open

seonwooj0810 wants to merge 1 commit into
OpenAPITools:masterfrom
seonwooj0810:fix/issue-24874-discriminator-property-ref-enum-default

Conversation

@seonwooj0810

@seonwooj0810 seonwooj0810 commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Fixes #24874

Bug

The Java client generator (default library: okhttp-gson) produced non-compiling code when a discriminator property is a $ref directly into another schema's inline enum property, rather than a $ref to a named enum schema:

this.category = String.ARCHIVE;

String.ARCHIVE does not exist, so the generated client fails to compile.

Root cause

DefaultCodegen#updateCodegenPropertyEnum resolves the enum default value and, whenever a matching enum entry is found, unconditionally calls toEnumDefaultValue(var, enumName) to qualify it with the property's datatype. That qualification is only meaningful when the property is itself an inline enum (var.isEnum) or resolves to a named enum schema (referencedSchema). For a discriminator property that is a $ref into another schema's property (not the enum schema itself), neither is true — var.datatypeWithEnum is just the raw scalar type (String) — yet the enum-matching logic still ran and produced a bogus qualified token.

This is exercised by okhttp-gson's pojo.mustache, which assigns the discriminator's default value in the generated subtype's constructor (other Java libraries don't emit this constructor-level assignment, which is why @jpfinne's comment on the issue pinned it to okhttp-gson specifically — the underlying bad value is computed generically in DefaultCodegen, okhttp-gson is just the template that surfaces it as a compile error).

Fix

Only call toEnumDefaultValue when var.isEnum || referencedSchema.isPresent(). Otherwise, drop the default (null) rather than emit an unqualified token that won't compile. The field is simply left unset in this edge case, which is the same as any other discriminator property whose caller must set it explicitly — no compile error, no incorrect value.

Test evidence

  • Added modules/openapi-generator/src/test/resources/bugs/issue_24874.yaml (the exact spec from the issue).
  • Added JavaClientCodegenTest#testDiscriminatorPropertyRefToEnumDoesNotEmitInvalidDefault_issue24874, which fails on current master (reproduces this.category = String.ARCHIVE; via fileDoesNotContain assertion) and passes with this fix.
  • Ran the full java-* sample set (bin/configs/java-*.yaml, 136 generators via bin/generate-samples.sh) — zero model/pojo diffs, confirming no existing committed sample exercises this narrow edge case and this change is safe.

Verification done

  1. No in-flight PR/linked branch for [BUG][java] Discriminator default for direct property enum $ref generates String.<value> #24874 (checked via gh issue view / gh api .../timeline).
  2. No active assignee/self-claim.
  3. Code-focused change (.java + test fixture only).
  4. Confirmed the bug still reproduces on latest upstream/master before the fix, and is resolved after.
  5. N/A (no parent epic).
  6. N/A (not spring-projects/*, no triage-pending gate).

Verification done: reproduced the exact compile failure from the issue on latest master using the issue's own minimal spec, confirmed root cause in DefaultCodegen#updateCodegenPropertyEnum, added a regression test that is red before / green after the fix, and confirmed zero sample diffs across the full java-* config set.


Summary by cubic

Fixes #24874. Stops the Java generator from emitting uncompilable defaults like this.category = String.ARCHIVE; when a discriminator property is a $ref to another schema's inline enum property — the default is now left unset instead of qualified with the raw scalar type.

Bug Fixes

  • toEnumDefaultValue is now only called when the property is an inline enum or resolves to a named enum schema; otherwise the default is null.
  • Added a regression test using the exact spec from the issue, which failed before this change.
  • Verified the full java-* sample set (136 generators) regenerates with zero diffs, so no existing sample is affected.

Written for commit 72f54fe. Summary will update on new commits.

Review in cubic

…to-property

A discriminator property that is a `$ref` to another schema's inline
enum property (rather than a ref to a named enum schema, or an inline
enum itself) still has its allowableValues/default resolved by
updateCodegenPropertyEnum, but there is no enum type at this property's
own use site to qualify the value with. toEnumDefaultValue was called
regardless, falling back to the raw (non-enum) datatype, producing
uninitializable code such as `this.category = String.ARCHIVE;` in the
okhttp-gson library's generated subtype constructor.

Only call toEnumDefaultValue when the property is actually an inline
enum (var.isEnum) or resolves to a named enum schema (referencedSchema);
otherwise drop the default rather than emit an unqualified token.

Verified the full java-* sample set (bin/configs/java-*.yaml, 136
generators) regenerates with zero model/pojo diffs, so no existing
sample exercises this edge case.

Fixes OpenAPITools#24874

@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.

1 issue found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java">

<violation number="1" location="modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java:7168">
P3: The else branch sets `var.defaultValue = null` for every non-enum, non-ref property with an enum constraint and matching default, not just the discriminator case it targets (#24874). For a non-discriminator String property that `$ref`s another schema's inline enum with a default, the field's default is silently dropped instead of emitting the still-valid raw literal (e.g. `this.category = "ARCHIVE";`), leaving the field uninitialized. Consider restoring the raw literal for `var.isString` when the intention is solely to avoid the bare `String.X` token.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

// allowableValues/enum matching still ran, but there's no enum constant to
// qualify the value with. Drop the default rather than emit a bare,
// unqualified token that would not compile (see #24874).
var.defaultValue = null;

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.

P3: The else branch sets var.defaultValue = null for every non-enum, non-ref property with an enum constraint and matching default, not just the discriminator case it targets (#24874). For a non-discriminator String property that $refs another schema's inline enum with a default, the field's default is silently dropped instead of emitting the still-valid raw literal (e.g. this.category = "ARCHIVE";), leaving the field uninitialized. Consider restoring the raw literal for var.isString when the intention is solely to avoid the bare String.X token.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java, line 7168:

<comment>The else branch sets `var.defaultValue = null` for every non-enum, non-ref property with an enum constraint and matching default, not just the discriminator case it targets (#24874). For a non-discriminator String property that `$ref`s another schema's inline enum with a default, the field's default is silently dropped instead of emitting the still-valid raw literal (e.g. `this.category = "ARCHIVE";`), leaving the field uninitialized. Consider restoring the raw literal for `var.isString` when the intention is solely to avoid the bare `String.X` token.</comment>

<file context>
@@ -7155,7 +7155,18 @@ public void updateCodegenPropertyEnum(CodegenProperty var) {
+                    // allowableValues/enum matching still ran, but there's no enum constant to
+                    // qualify the value with. Drop the default rather than emit a bare,
+                    // unqualified token that would not compile (see #24874).
+                    var.defaultValue = null;
+                }
             }
</file context>

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] Discriminator default for direct property enum $ref generates String.<value>

1 participant