From 024ce3a09a83b91acbfe22f5d9215fd65bf93843 Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Tue, 13 Jan 2026 16:04:44 +0100 Subject: [PATCH] Resolve vendor extensions on schemas referenced in parameters. fixes #9138 --- .../openapitools/codegen/DefaultCodegen.java | 7 +-- .../java/spring/SpringCodegenTest.java | 48 +++++++++++++++++++ ...sue_9138_resolve_extensions_on_schema.yaml | 32 +++++++++++++ 3 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue_9138_resolve_extensions_on_schema.yaml 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 0695e32687e3..35beeba016f8 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 @@ -5349,9 +5349,6 @@ public CodegenParameter fromParameter(Parameter parameter, Set imports) if (parameter.getExtensions() != null && !parameter.getExtensions().isEmpty()) { codegenParameter.vendorExtensions.putAll(parameter.getExtensions()); } - if (parameter.getSchema() != null && parameter.getSchema().getExtensions() != null && !parameter.getSchema().getExtensions().isEmpty()) { - codegenParameter.vendorExtensions.putAll(parameter.getSchema().getExtensions()); - } Schema parameterSchema; @@ -5386,6 +5383,10 @@ public CodegenParameter fromParameter(Parameter parameter, Set imports) parameterSchema = null; } + if (parameterSchema != null && parameterSchema.getExtensions() != null && !parameterSchema.getExtensions().isEmpty()) { + codegenParameter.vendorExtensions.putAll(parameterSchema.getExtensions()); + } + if (parameter instanceof QueryParameter || "query".equalsIgnoreCase(parameter.getIn())) { codegenParameter.isQueryParam = true; codegenParameter.isAllowEmptyValue = parameter.getAllowEmptyValue() != null && parameter.getAllowEmptyValue(); 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 bd2c822f4322..11ca74f3e534 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 @@ -6175,4 +6175,52 @@ public void annotationLibraryDoesNotCauseImportConflictsInSpringWithAnnotationLi "import io.swagger.v3.oas.annotations.media.Schema;" ); } + + @Test + public void testExtensionsOnSchema_issue9183() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_9138_resolve_extensions_on_schema.yaml"); + final SpringCodegen codegen = new SpringCodegen(); + codegen.setOpenAPI(openAPI); + codegen.setOutputDir(output.getAbsolutePath()); + + codegen.additionalProperties().put(SpringCodegen.DATE_LIBRARY, "java8-localdatetime"); + codegen.additionalProperties().put(INTERFACE_ONLY, "true"); + codegen.additionalProperties().put(USE_RESPONSE_ENTITY, "false"); + codegen.additionalProperties().put(DELEGATE_PATTERN, "true"); + codegen.additionalProperties().put(USE_BEANVALIDATION, "true"); + codegen.additionalProperties().put(PERFORM_BEANVALIDATION, "true"); + codegen.additionalProperties().put(REQUEST_MAPPING_OPTION, "api_interface"); + + ClientOptInput input = new ClientOptInput(); + input.openAPI(openAPI); + input.config(codegen); + + DefaultGenerator generator = new DefaultGenerator(); + generator.setGenerateMetadata(false); // skip metadata generation + + Map files = generator.opts(input).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + JavaFileAssert javaFileAssert = JavaFileAssert.assertThat(files.get("TestApi.java")); + javaFileAssert + .assertMethod("_postToTest") + .assertParameter("groupObj") + .assertParameterAnnotations() + .containsWithNameAndAttributes("Pattern", ImmutableMap.of( + "regexp", "\"[a-zA-Z]\"", + "message", "\"Only letters\"" + )) + .toParameter() + .toMethod() + .assertParameter("token") + .assertParameterAnnotations() + .containsWithNameAndAttributes("Pattern", ImmutableMap.of( + "regexp", "\"[0-9a-fA-F]\"", + "message", "\"Only numbers and letters a-f\"" + )); + } + } diff --git a/modules/openapi-generator/src/test/resources/3_0/issue_9138_resolve_extensions_on_schema.yaml b/modules/openapi-generator/src/test/resources/3_0/issue_9138_resolve_extensions_on_schema.yaml new file mode 100644 index 000000000000..f861ddee7439 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue_9138_resolve_extensions_on_schema.yaml @@ -0,0 +1,32 @@ +openapi: 3.0.3 +info: + title: sample spec + version: 1.0.0 +paths: + /test/{groupObj}: + post: + summary: Post to test + description: '' + operationId: postToTest + parameters: + - in: path + name: groupObj + required: true + schema: + $ref: '#/components/schemas/OnlyLetters' + - in: query + name: token + required: true + schema: + type: string + pattern: "[0-9a-fA-F]" + x-pattern-message: "Only numbers and letters a-f" + responses: + 201: + description: success +components: + schemas: + OnlyLetters: + type: string + pattern: "[a-zA-Z]" + x-pattern-message: "Only letters"