From c4a41aaacfe9b6cb6dea7b8f0474346037e905de Mon Sep 17 00:00:00 2001 From: Anupam Chaubey Date: Sun, 9 Aug 2026 22:38:34 +0530 Subject: [PATCH 1/6] fix(java-spring): expose requestBody named examples to Mustache template context (#23607) --- .../languages/AbstractJavaCodegen.java | 3 ++ .../java/spring/SpringCodegenTest.java | 34 ++++++++++++++++++ .../spring/requestbody_named_examples.yaml | 36 +++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 modules/openapi-generator/src/test/resources/3_0/spring/requestbody_named_examples.yaml diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index ec6d25ed5ff3..80530aa3956c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -1782,6 +1782,9 @@ public void setParameterExampleValue(CodegenParameter codegenParameter, RequestB } if (mediaType.getExamples() != null && !mediaType.getExamples().isEmpty()) { + // FIX for #23607: Assign all named examples to the parameter so Mustache templates can access them + codegenParameter.examples = mediaType.getExamples(); + Example example = mediaType.getExamples().values().iterator().next(); if (example.getValue() != null) { if (isModel) { 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 c8d289dc2320..2776d9219398 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 @@ -8690,4 +8690,38 @@ public void testReactiveSpringHttpInterfaceSupportListOfStringReturnTypeNoRespon "Mono> getUserIdSet" ); } + + @Test + public void shouldExposeRequestBodyNamedExamplesToTemplateContext_issue23607() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + + OpenAPI openAPI = new OpenAPIParser().readLocation( + "src/test/resources/3_0/spring/requestbody_named_examples.yaml", + null, + new ParseOptions() + ).getOpenAPI(); + + SpringCodegen codegen = new SpringCodegen(); + codegen.setOutputDir(output.getAbsolutePath()); + codegen.additionalProperties().put(INTERFACE_ONLY, "true"); + + ClientOptInput input = new ClientOptInput(); + input.openAPI(openAPI); + input.config(codegen); + + DefaultGenerator generator = new DefaultGenerator(); + generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true"); + generator.setGenerateMetadata(false); + generator.opts(input).generate(); + + // Verify via codegen operation inspection after initialization + Operation operation = openAPI.getPaths().get("/users").getPost(); + CodegenOperation codegenOperation = codegen.fromOperation("/users", "POST", operation, null); + + assertNotNull(codegenOperation.bodyParam); + assertNotNull(codegenOperation.bodyParam.examples); + assertTrue(codegenOperation.bodyParam.examples.containsKey("Jessica")); + assertTrue(codegenOperation.bodyParam.examples.containsKey("Ron")); + } } \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/spring/requestbody_named_examples.yaml b/modules/openapi-generator/src/test/resources/3_0/spring/requestbody_named_examples.yaml new file mode 100644 index 000000000000..cde7811839e0 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/spring/requestbody_named_examples.yaml @@ -0,0 +1,36 @@ +openapi: 3.0.0 +info: + title: Example API + version: 1.0.0 +paths: + /users: + post: + summary: Adds a new user + tags: + - User + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/User" + examples: + Jessica: + value: + id: 10 + name: Jessica Smith + Ron: + value: + id: 11 + name: Ron Stewart + responses: + "200": + description: OK +components: + schemas: + User: + type: object + properties: + id: + type: integer + name: + type: string \ No newline at end of file From 5ec4bff10fec197ff8e2a8637d1b27f29fa5d09a Mon Sep 17 00:00:00 2001 From: Anupam Chaubey Date: Thu, 13 Aug 2026 18:19:29 +0530 Subject: [PATCH 2/6] fix(java-spring): preprocess OpenAPI in unit test to avoid NPE --- .../codegen/java/spring/SpringCodegenTest.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) 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 598d1fe1a7e8..42a398144248 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 @@ -8693,9 +8693,6 @@ public void testReactiveSpringHttpInterfaceSupportListOfStringReturnTypeNoRespon @Test public void shouldExposeRequestBodyNamedExamplesToTemplateContext_issue23607() throws IOException { - File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); - output.deleteOnExit(); - OpenAPI openAPI = new OpenAPIParser().readLocation( "src/test/resources/3_0/spring/requestbody_named_examples.yaml", null, @@ -8703,17 +8700,10 @@ public void shouldExposeRequestBodyNamedExamplesToTemplateContext_issue23607() t ).getOpenAPI(); SpringCodegen codegen = new SpringCodegen(); - codegen.setOutputDir(output.getAbsolutePath()); codegen.additionalProperties().put(INTERFACE_ONLY, "true"); - ClientOptInput input = new ClientOptInput(); - input.openAPI(openAPI); - input.config(codegen); - - DefaultGenerator generator = new DefaultGenerator(); - generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true"); - generator.setGenerateMetadata(false); - generator.opts(input).generate(); + // Preprocess OpenAPI to initialize extensions and internal structures required by SpringCodegen + codegen.preprocessOpenAPI(openAPI); // Verify via codegen operation inspection after initialization Operation operation = openAPI.getPaths().get("/users").getPost(); From 5f90fdd3f45156ee0a91a11ffb0d35dcd7d19531 Mon Sep 17 00:00:00 2001 From: Anupam Chaubey Date: Thu, 13 Aug 2026 18:32:16 +0530 Subject: [PATCH 3/6] fix(java-spring): call codegen.setOpenAPI in unit test to mirror DefaultGenerator --- .../openapitools/codegen/java/spring/SpringCodegenTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 42a398144248..b487548021cb 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 @@ -8702,8 +8702,9 @@ public void shouldExposeRequestBodyNamedExamplesToTemplateContext_issue23607() t SpringCodegen codegen = new SpringCodegen(); codegen.additionalProperties().put(INTERFACE_ONLY, "true"); - // Preprocess OpenAPI to initialize extensions and internal structures required by SpringCodegen + // Preprocess and set OpenAPI to mirror DefaultGenerator behavior codegen.preprocessOpenAPI(openAPI); + codegen.setOpenAPI(openAPI); // Verify via codegen operation inspection after initialization Operation operation = openAPI.getPaths().get("/users").getPost(); From ee46e4ba4434ef1f134b071ea19789c46c32eefa Mon Sep 17 00:00:00 2001 From: Anupam Chaubey Date: Thu, 13 Aug 2026 22:11:13 +0530 Subject: [PATCH 4/6] feat(codegen): move requestbody named examples logic globally to DefaultCodegen --- .../openapitools/codegen/DefaultCodegen.java | 24 ++++++++++++ .../languages/AbstractJavaCodegen.java | 38 ------------------- 2 files changed, 24 insertions(+), 38 deletions(-) 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 1e8d2c7b181e..096deef15c74 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 @@ -2454,6 +2454,23 @@ public void setParameterExamples(CodegenParameter codegenParameter, Parameter pa } } + /** + * Return the examples of the request body parameter. + * + * @param codegenParameter Codegen parameter + * @param requestBody Request body + */ + public void setParameterExamples(CodegenParameter codegenParameter, RequestBody requestBody) { + if (requestBody.getContent() != null && !requestBody.getContent().isEmpty()) { + for (MediaType mediaType : requestBody.getContent().values()) { + if (mediaType.getExamples() != null && !mediaType.getExamples().isEmpty()) { + codegenParameter.examples = mediaType.getExamples(); + break; + } + } + } + } + /** * Return the example value of the parameter. * @@ -2463,6 +2480,13 @@ public void setParameterExamples(CodegenParameter codegenParameter, Parameter pa public void setParameterExampleValue(CodegenParameter codegenParameter, RequestBody requestBody) { Content content = requestBody.getContent(); + if (content != null && !content.isEmpty()) { + MediaType mediaType = content.values().iterator().next(); + if (mediaType.getExamples() != null && !mediaType.getExamples().isEmpty()) { + codegenParameter.examples = mediaType.getExamples(); + } + } + Optional contentExample = ExamplesUtils.getContentExample(content); if (contentExample.isPresent()) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index 34a8784b5531..1ab1b7b78fb0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -1751,44 +1751,6 @@ public void setParameterExampleValue(CodegenParameter codegenParameter, Paramete setParameterExampleValue(codegenParameter); } - - /** - * Return the example value of the parameter. Overrides the parent method in DefaultCodegen - * to not set examples on complex models, as they don't compile properly. - * - * @param codegenParameter Codegen parameter - * @param requestBody Request body - */ - @Override - public void setParameterExampleValue(CodegenParameter codegenParameter, RequestBody requestBody) { - if (requestBody.getContent() != null && !requestBody.getContent().isEmpty()) { - boolean isModel = (codegenParameter.isModel || (codegenParameter.isContainer && codegenParameter.getItems().isModel)); - - MediaType mediaType = requestBody.getContent().values().iterator().next(); - boolean hasExample = mediaType.getExample() != null || (mediaType.getExamples() != null && !mediaType.getExamples().isEmpty()); - if (isModel) { - if (hasExample) { - once(LOGGER).warn("Ignoring complex example on request body"); - } - } - - // FIX for #23607: Assign all named examples to the parameter so Mustache templates can access them - if (mediaType.getExamples() != null && !mediaType.getExamples().isEmpty()) { - codegenParameter.examples = mediaType.getExamples(); - - if (!isModel) { - Example example = mediaType.getExamples().values().iterator().next(); - if (example.getValue() != null) { - codegenParameter.example = example.getValue().toString(); - return; - } - } - } - setParameterExampleValue(codegenParameter); - } else { - super.setParameterExampleValue(codegenParameter, requestBody); - } - } @Override public void setParameterExampleValue(CodegenParameter p) { From 37b4154ec6e4b53811538f73e2643ee08c844fb5 Mon Sep 17 00:00:00 2001 From: Anupam Chaubey Date: Thu, 13 Aug 2026 22:25:04 +0530 Subject: [PATCH 5/6] fix(codegen): use setParameterExamples helper in setParameterExampleValue and update samples --- .../java/org/openapitools/codegen/DefaultCodegen.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) 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 096deef15c74..803e896d640d 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 @@ -2480,12 +2480,8 @@ public void setParameterExamples(CodegenParameter codegenParameter, RequestBody public void setParameterExampleValue(CodegenParameter codegenParameter, RequestBody requestBody) { Content content = requestBody.getContent(); - if (content != null && !content.isEmpty()) { - MediaType mediaType = content.values().iterator().next(); - if (mediaType.getExamples() != null && !mediaType.getExamples().isEmpty()) { - codegenParameter.examples = mediaType.getExamples(); - } - } + // Reuse the helper method to correctly catch examples across all media types + setParameterExamples(codegenParameter, requestBody); Optional contentExample = ExamplesUtils.getContentExample(content); From 0ef86e71a9cb44ebab9211931c889db9e67edf13 Mon Sep 17 00:00:00 2001 From: Anupam Chaubey Date: Thu, 13 Aug 2026 22:57:53 +0530 Subject: [PATCH 6/6] fix(codegen): invoke setParameterExamples globally inside fromRequestBody --- .../java/org/openapitools/codegen/DefaultCodegen.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) 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 803e896d640d..99b238f6046e 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 @@ -8310,6 +8310,9 @@ public CodegenParameter fromRequestBody(RequestBody body, Set imports, S codegenParameter.vendorExtensions.putAll(body.getExtensions()); } + // Ensure request body named examples are populated globally for ALL generators + setParameterExamples(codegenParameter, body); + String name = null; LOGGER.debug("Request body = {}", body); Schema schema = ModelUtils.getSchemaFromRequestBody(body); @@ -8437,11 +8440,6 @@ public CodegenParameter fromRequestBody(RequestBody body, Set imports, S if (original.getMinimum() != null) { codegenParameter.setMinimum(String.valueOf(original.getMinimum().doubleValue())); } - /* comment out below as we don't store `title` in the codegen parametera the moment - if (original.getTitle() != null) { - codegenParameter.setTitle(original.getTitle()); - } - */ } return codegenParameter;