Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1759,22 +1759,37 @@ public void setParameterExampleValue(CodegenParameter codegenParameter, Paramete
* @param codegenParameter Codegen parameter
* @param requestBody Request body
*/
@Override
@Override
public void setParameterExampleValue(CodegenParameter codegenParameter, RequestBody requestBody) {
boolean isModel = (codegenParameter.isModel || (codegenParameter.isContainer && codegenParameter.getItems().isModel));
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();

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");
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) {
String example;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8690,4 +8690,38 @@ public void testReactiveSpringHttpInterfaceSupportListOfStringReturnTypeNoRespon
"Mono<Set<String>> 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();

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 test starts a full generator run into a temp directory and computes an outputPath variable, but the actual assertions never read the generated files — they call codegen.fromOperation(...) directly and check the returned bodyParam.examples map. As written, the DefaultGenerator + generate() block and the outputPath variable are dead scaffolding that adds runtime cost and noise without verifying anything. I'd suggest dropping the unused outputPath and either removing the redundant generator execution, or better, asserting on the rendered template output if the goal is to prove Mustache exposure.

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

<comment>The test starts a full generator run into a temp directory and computes an `outputPath` variable, but the actual assertions never read the generated files — they call `codegen.fromOperation(...)` directly and check the returned `bodyParam.examples` map. As written, the `DefaultGenerator` + `generate()` block and the `outputPath` variable are dead scaffolding that adds runtime cost and noise without verifying anything. I'd suggest dropping the unused `outputPath` and either removing the redundant generator execution, or better, asserting on the rendered template output if the goal is to prove Mustache exposure.</comment>

<file context>
@@ -8690,4 +8690,43 @@ public void testReactiveSpringHttpInterfaceSupportListOfStringReturnTypeNoRespon
+        generator.setGenerateMetadata(false);
+
+        // Run generator
+        generator.opts(input).generate();
+
+        // Verify or test directly via CodegenOperation model inspection
</file context>


// 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"));
}
}
Original file line number Diff line number Diff line change
@@ -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
Loading