diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index ddae177f7b85..34ad7d0a049a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -7155,7 +7155,25 @@ public void updateCodegenPropertyEnum(CodegenProperty var) { } } if (enumName != null) { - var.defaultValue = toEnumDefaultValue(var, enumName); + if (var.isEnum || !languageSpecificPrimitives.contains(varDataType)) { + var.defaultValue = toEnumDefaultValue(var, enumName); + } else { + // Not an inline nested enum (var.isEnum) and varDataType is a raw + // language-specific primitive (e.g. "String"): there's no enum class at + // this use site to qualify the value with (e.g. a discriminator property + // that is a `$ref` into another schema's property rather than a ref to the + // enum schema itself). allowableValues/enum matching still ran, but + // emitting a bare, unqualified token like `String.ARCHIVE` would not + // compile. Drop the default instead (see #24874). + // + // Note: this check is intentionally based on languageSpecificPrimitives + // rather than referencedSchema.isPresent() — referencedSchema's name match + // against the raw dataType string is brittle for codegens whose dataType is + // namespace/package-qualified (e.g. PHP's `OpenAPI\Server\Model\Foo`), which + // would never match `toModelName(...)` and incorrectly drop valid enum + // defaults for genuine named-enum refs. + var.defaultValue = null; + } } } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java index 12cbe5bd2cd7..272e05a611dc 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java @@ -1869,6 +1869,27 @@ public void testObjectDefaultWithEnumProperty_issue24298() { .contains("new OutputFormat().order(OutputFormat.OrderEnum.SIMILARITY).limit(10)"); } + @Test + public void testDiscriminatorPropertyRefToEnumDoesNotEmitInvalidDefault_issue24874() { + final Path output = newTempFolder(); + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName(JAVA_GENERATOR) + .setInputSpec("src/test/resources/bugs/issue_24874.yaml") + .setAdditionalProperties(Map.of(MODEL_NAME_PREFIX, "Stock")) + .setOutputDir(output.toString().replace("\\", "/")); + + Map files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + // CategoryEvent.category is a discriminator property that is a `$ref` to another schema's + // (CategorySource) inline enum property, not to a named enum schema and not an inline enum + // itself. There is no enum type at this use site to qualify the discriminator mapping value + // with, so no default must be emitted here; previously this rendered the uncompilable + // `this.category = String.ARCHIVE;` (see #24874). + JavaFileAssert.assertThat(files.get("StockArchiveCategoryEvent.java")) + .fileDoesNotContain("String.ARCHIVE"); + } + @Test public void testWebClientJsonCreatorWithNullable_issue12790() { final Path output = newTempFolder(); diff --git a/modules/openapi-generator/src/test/resources/bugs/issue_24874.yaml b/modules/openapi-generator/src/test/resources/bugs/issue_24874.yaml new file mode 100644 index 000000000000..6d7267dcce6c --- /dev/null +++ b/modules/openapi-generator/src/test/resources/bugs/issue_24874.yaml @@ -0,0 +1,35 @@ +openapi: "3.1.0" +info: + title: Shared category discriminator + version: 1.0.0 +paths: {} +components: + schemas: + CategorySource: + type: object + required: + - category + properties: + category: + type: string + enum: + - ARCHIVE + CategoryEvent: + type: object + required: + - category + properties: + category: + description: Event category + $ref: "#/components/schemas/CategorySource/properties/category" + discriminator: + propertyName: category + mapping: + ARCHIVE: "#/components/schemas/ArchiveCategoryEvent" + ArchiveCategoryEvent: + allOf: + - $ref: "#/components/schemas/CategoryEvent" + - type: object + properties: + value: + type: string