From 96b3488a0779d1810f29b75ac12bc993c4b163e2 Mon Sep 17 00:00:00 2001 From: JanLubenow <44801057+JanLubenow@users.noreply.github.com> Date: Tue, 13 Jun 2023 15:13:31 +0200 Subject: [PATCH] [BUG] [Java-Spring] Required-Fields-Constructor has wrong super call when using multiple inheritance layers (#15827) * (fix): required-fields constructor uses super-call-parameters in the order of the parent required-field constructor * (fix): required-fields constructor uses super-call-parameters in the order of the parent required-field constructor - add issue number * (fix): required-fields constructor uses super-call-parameters in the order of the parent required-field constructor - fix file reference --- .../codegen/languages/SpringCodegen.java | 7 +- .../java/spring/SpringCodegenTest.java | 42 +++++++++ ...ired-values-with-multiple-inheritance.yaml | 94 +++++++++++++++++++ 3 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/bugs/issue_constructor-required-values-with-multiple-inheritance.yaml diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java index 2f99d3f81ed..a9a0df1b49b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java @@ -1174,14 +1174,13 @@ public class SpringCodegen extends AbstractJavaCodegen codegenModel.getImports().add(imp); } } - - if (property.required) { - codegenModel.parentRequiredVars.add(parentVar.clone()); - } } } parentCodegenModel = parentCodegenModel.getParentModel(); } + if (codegenModel.getParentModel() != null) { + codegenModel.parentRequiredVars = new ArrayList<>(codegenModel.getParentModel().requiredVars); + } // There must be a better way ... for (String imp: inheritedImports) { String qimp = importMapping().get(imp); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java index 5900a4a7e35..c329ed9fcd5 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java @@ -26,9 +26,11 @@ import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.parser.core.models.ParseOptions; import org.openapitools.codegen.*; +import org.openapitools.codegen.config.CodegenConfigurator; import org.openapitools.codegen.config.GlobalSettings; import org.openapitools.codegen.java.assertions.JavaFileAssert; import org.openapitools.codegen.languages.AbstractJavaCodegen; +import org.openapitools.codegen.languages.JavaClientCodegen; import org.openapitools.codegen.languages.SpringCodegen; import org.openapitools.codegen.languages.features.BeanValidationFeatures; import org.openapitools.codegen.languages.features.CXFServerFeatures; @@ -388,6 +390,46 @@ public class SpringCodegenTest { .containsWithNameAndAttributes("DateTimeFormat", ImmutableMap.of("iso", "DateTimeFormat.ISO.DATE_TIME")); } + @Test + public void testJavaClientCorrectConstructorOrderForRequiredFields_issue15825() throws IOException { + Map properties = new HashMap<>(); + properties.put(JavaClientCodegen.MICROPROFILE_REST_CLIENT_VERSION, "3.0"); + + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setAdditionalProperties(properties) + .setGeneratorName("spring") + .setLibrary(SPRING_BOOT) + .setInputSpec("src/test/resources/bugs/issue_constructor-required-values-with-multiple-inheritance.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + final ClientOptInput clientOptInput = configurator.toClientOptInput(); + DefaultGenerator generator = new DefaultGenerator(); + Map files = generator.opts(clientOptInput).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + JavaFileAssert.assertThat(files.get("SubType.java")) + .assertConstructor("TypeEnum", "SchemaVersion", "UUID", "Boolean", "Boolean", "SomeEnum") + .bodyContainsLines("super(someBoolean, someEnum, schemaVersion, id, oneBoolean);", + "this.type = type;"); + JavaFileAssert.assertThat(files.get("IntermediateSubType.java")) + .assertConstructor("Boolean", "SomeEnum", "SchemaVersion", "UUID", "Boolean") + .bodyContainsLines("super(oneBoolean, schemaVersion, id);", + "this.someBoolean = someBoolean;", + "this.someEnum = someEnum"); + JavaFileAssert.assertThat(files.get("IntermediateType.java")) + .assertConstructor("Boolean", "SchemaVersion", "UUID") + .bodyContainsLines("super(schemaVersion, id);", + "this.oneBoolean = oneBoolean;"); + JavaFileAssert.assertThat(files.get("BaseType.java")) + .assertConstructor("SchemaVersion", "UUID") + .bodyContainsLines( + "this.schemaVersion = schemaVersion;", + "this.id = id;"); + } + @Test public void springcloudWithAsyncAndJava8HasResponseWrapperCompletableFuture() { final SpringCodegen codegen = new SpringCodegen(); diff --git a/modules/openapi-generator/src/test/resources/bugs/issue_constructor-required-values-with-multiple-inheritance.yaml b/modules/openapi-generator/src/test/resources/bugs/issue_constructor-required-values-with-multiple-inheritance.yaml new file mode 100644 index 00000000000..5a686088f4d --- /dev/null +++ b/modules/openapi-generator/src/test/resources/bugs/issue_constructor-required-values-with-multiple-inheritance.yaml @@ -0,0 +1,94 @@ +--- +openapi: 3.0.2 +info: + version: 0.0.0 + title: Wrong Constructor + +paths: {} + +components: + + schemas: + BaseType: + type: object + required: + - schemaVersion + - id + properties: + schemaVersion: + $ref: "#/components/schemas/SchemaVersion" + id: + type: string + format: "uuid" + freeTextField: + type: array + default: [ ] + minItems: 0 + maxItems: 6 + items: + type: string + maxLength: 255 + discriminator: + propertyName: type + mapping: + SubType: "#/components/schemas/SubType" + + + IntermediateType: + allOf: + - $ref: "#/components/schemas/BaseType" + - type: object + required: + - OneBoolean + properties: + OneBoolean: + type: boolean + default: false + OneOptionalBoolean: + type: boolean + default: false + + IntermediateSubType: + allOf: + - $ref: "#/components/schemas/IntermediateType" + - type: object + required: + - someBoolean + - someEnum + properties: + someBoolean: + type: boolean + default: false + someEnum: + $ref: "#/components/schemas/SomeEnum" + + SubType: + allOf: + - $ref: "#/components/schemas/IntermediateSubType" + - type: object + properties: + type: + type: string + default: "SubType" + enum: [ "SubType" ] + required: + - type + + + SomeEnum: + type: string + enum: + - LIT1 + - LIT2 + x-enum-varnames: + - Literal1 + - Literal2 + + + SchemaVersion: + type: string + default: "1.0.0" + x-enum-varnames: + - CURRENT + enum: + - "1.0.0"