Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Java][Spring] Fix formParams template to add support for default values when generating @RequestParam annotation for parameters included in a body with content: application/x-www-form-urlencoded #20314

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
@@ -1 +1 @@
{{#isFormParam}}{{^isFile}}{{>paramDoc}}{{#useBeanValidation}} @Valid{{/useBeanValidation}} {{#isModel}}@RequestPart{{/isModel}}{{^isModel}}{{#isArray}}@RequestPart{{/isArray}}{{^isArray}}{{#reactive}}@RequestPart{{/reactive}}{{^reactive}}@RequestParam{{/reactive}}{{/isArray}}{{/isModel}}(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}){{>dateTimeParam}} {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{>paramDoc}} @RequestPart(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{#isArray}}List<{{/isArray}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}} {{paramName}}{{/isFile}}{{/isFormParam}}
{{#isFormParam}}{{^isFile}}{{>paramDoc}}{{#useBeanValidation}} @Valid{{/useBeanValidation}} {{#isModel}}@RequestPart{{/isModel}}{{^isModel}}{{#isArray}}@RequestPart{{/isArray}}{{^isArray}}{{#reactive}}@RequestPart{{/reactive}}{{^reactive}}@RequestParam{{/reactive}}{{/isArray}}{{/isModel}}(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}{{#defaultValue}}, defaultValue = "{{{.}}}"{{/defaultValue}}){{>dateTimeParam}} {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{>paramDoc}} @RequestPart(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{#isArray}}List<{{/isArray}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}} {{paramName}}{{/isFile}}{{/isFormParam}}
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ public void shouldUseTagsForClassname() throws IOException {

DefaultGenerator generator = new DefaultGenerator();
generator.setGenerateMetadata(false);

Map<String, File> files = generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));

Expand Down Expand Up @@ -1664,7 +1664,7 @@ public void testOneOf5381() throws IOException {
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "false");

codegen.setUseOneOfInterfaces(true);
codegen.setLegacyDiscriminatorBehavior(false);

Expand Down Expand Up @@ -2676,7 +2676,7 @@ public void contractWithResolvedInnerEnumContainsEnumConverter() throws IOExcept
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
generator.setGenerateMetadata(false);

Map<String, File> files = generator.opts(clientOptInput).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));

Expand All @@ -2701,7 +2701,7 @@ public void shouldUseTheSameTagNameForTheInterfaceAndTheMethod_issue11570() thro
@Test
public void shouldGenerateConstructorWithOnlyRequiredParameters() throws IOException {
final Map<String, File> output = generateFromContract(
"src/test/resources/3_0/spring/issue_9789.yml",
"src/test/resources/3_0/spring/issue_9789.yml",
SPRING_BOOT,
Map.of(GENERATE_CONSTRUCTOR_WITH_ALL_ARGS, "false")
);
Expand Down Expand Up @@ -4378,7 +4378,7 @@ public void testModelsWithNoneOptionalAndNoneOpenApiNullable() throws IOExceptio
assertMethod(javaFileAssert, BigDecimal.class, "numberMaxNullable");

}

private void assertOptionalMethod(JavaFileAssert javaFileAssert, Class<?> type, String expectedName, String getterReturnType){
assertOptionalMethod(javaFileAssert, type.getSimpleName(), expectedName, getterReturnType);
}
Expand Down Expand Up @@ -4718,8 +4718,8 @@ public void generateAllArgsConstructor() throws IOException {
@Test
public void allOfDuplicatedProperties() throws IOException {
Map<String, File> output = generateFromContract(
"src/test/resources/3_0/allOfDuplicatedProperties.yaml",
SPRING_BOOT,
"src/test/resources/3_0/allOfDuplicatedProperties.yaml",
SPRING_BOOT,
Map.of(GENERATE_CONSTRUCTOR_WITH_ALL_ARGS, true, INTERFACE_ONLY, "true")
);

Expand Down Expand Up @@ -4775,11 +4775,11 @@ public void testLombokAnnotations() throws IOException {
@Test
void testBuilderJavaSpring_noOptional() throws IOException {
Map<String, File> files = generateFromContract(
"src/test/resources/3_0/java/builder.yaml",
"src/test/resources/3_0/java/builder.yaml",
SPRING_BOOT,
Map.of(
GENERATE_BUILDERS, true,
SpringCodegen.OPENAPI_NULLABLE, false,
GENERATE_BUILDERS, true,
SpringCodegen.OPENAPI_NULLABLE, false,
SpringCodegen.USE_OPTIONAL, false,
INTERFACE_ONLY, "true"
)
Expand All @@ -4804,7 +4804,7 @@ void testBuilderJavaSpring_noOptional() throws IOException {
@Test
void testBuilderJavaSpring_useOptional() throws IOException {
Map<String, File> files = generateFromContract(
"src/test/resources/3_0/java/builder.yaml",
"src/test/resources/3_0/java/builder.yaml",
SPRING_BOOT,
Map.of(
GENERATE_BUILDERS, true,
Expand Down Expand Up @@ -4854,7 +4854,7 @@ public void optionalListShouldBeEmpty() throws IOException {
DefaultGenerator generator = new DefaultGenerator();
generator.setGenerateMetadata(false); // skip metadata and ↓ only generate models
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");

Map<String, File> files = generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));

Expand Down Expand Up @@ -4888,7 +4888,7 @@ public void testCollectionTypesWithDefaults_issue_18102() throws IOException {
DefaultGenerator generator = new DefaultGenerator();
generator.setGenerateMetadata(false); // skip metadata and ↓ only generate models
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");

Map<String, File> files = generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));

Expand Down Expand Up @@ -5003,15 +5003,15 @@ public void testEnumUnknownDefaultCaseDeserializationNotSet_issue13241() throws
.hasAnnotation("JacksonXmlElementWrapper", Map.of("useWrapping", "false"))
.toFileAssert()

// ↓ test custom element name (https://swagger.io/docs/specification/data-models/representing-xml/#:~:text=Change%20Element%20Names)
// ↓ test custom element name (https://swagger.io/docs/specification/data-models/representing-xml/#:~:text=Change%20Element%20Names)
.assertMethod("getStatus")
.doesNotHaveAnnotation("XmlAttribute")
.doesNotHaveAnnotation("XmlElementWrapper")
.hasAnnotation("XmlElement", Map.of("name", "\"PetStatus\""))
.doesNotHaveAnnotation("JacksonXmlElementWrapper")
.hasAnnotation("JacksonXmlProperty", Map.of("localName", "\"PetStatus\""))
.toFileAssert()

// ↓ test same-name wrapping element (https://swagger.io/docs/specification/data-models/representing-xml/#:~:text=Wrapping%20Arrays)
// maps to 3rd example in https://spec.openapis.org/oas/v3.0.0#xml-arrays
.assertMethod("getPhotoUrls")
Expand Down Expand Up @@ -5048,7 +5048,7 @@ public void testEnumUnknownDefaultCaseDeserializationNotSet_issue13241() throws
.hasAnnotation("JacksonXmlProperty", Map.of("localName", "\"yummy-yummy\""))
.hasAnnotation("JacksonXmlElementWrapper", Map.of("localName", "\"yummy-yummy\""))
.toFileAssert()

// ↓ internal xml-array element name (4th example in https://spec.openapis.org/oas/v3.0.0#xml-arrays)
.assertMethod("getColors")
.doesNotHaveAnnotation("XmlAttribute")
Expand All @@ -5057,7 +5057,7 @@ public void testEnumUnknownDefaultCaseDeserializationNotSet_issue13241() throws
.hasAnnotation("JacksonXmlProperty", Map.of("localName", "\"color\""))
.hasAnnotation("JacksonXmlElementWrapper", Map.of("localName", "\"colors\""))
.toFileAssert()

// ↓ ignored external xml-array element name, non-wrapped (2nd example in https://spec.openapis.org/oas/v3.0.0#xml-arrays)
.assertMethod("getCategories")
.doesNotHaveAnnotation("XmlAttribute")
Expand All @@ -5077,7 +5077,7 @@ public void testEnumUnknownDefaultCaseDeserializationNotSet_issue13241() throws
.hasAnnotation("JacksonXmlProperty", Map.of("localName", "\"item\""))
.hasAnnotation("JacksonXmlElementWrapper", Map.of("localName", "\"activities-array\""));
}

/**
* Regression test for <a href="https://github.com/OpenAPITools/openapi-generator/issues/12804">#12804</a>
*/
Expand All @@ -5099,4 +5099,28 @@ public void testEnumUnknownDefaultCaseDeserializationNotSet_issue13241() throws
.assertMethod("build")
.doesNotHaveAnnotation("Deprecated");
}

@Test
public void testRequestBodyFormParamsDefaultValue() {
final var tempDir = TestUtils.newTempFolder();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setInputSpec("src/test/resources/3_0/spring/formParams_defaultValue.yaml")
.setGeneratorName("spring")
.setOutputDir(tempDir.toString());

new DefaultGenerator().opts(configurator.toClientOptInput()).generate();

JavaFileAssert.assertThat(tempDir.resolve("src/main/java/org/openapitools/api/SomeApi.java"))
.assertMethod("someDummyEndpoint", "String", "String")
.assertParameter("productId")
.assertParameterAnnotations()
.containsWithNameAndAttributes("RequestParam",
Map.of("value", "\"product_id\"", "required", "true"))
.toParameter().toMethod()
.assertParameter("locale")
.assertParameterAnnotations()
.containsWithNameAndAttributes("RequestParam",
Map.of("value", "\"locale\"", "required", "false", "defaultValue", "\"en_US\""));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
openapi: 3.0.0
info:
version: "1.0.0"
title: formParams-defaultValue-test
paths:
/some/dummy/endpoint:
post:
operationId: someDummyEndpoint
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/DummyRequest'
responses:
200:
description: Successfully created
content:
application/json:
schema:
type: object
additionalProperties:
$ref: '#/components/schemas/DummyResponse'
components:
schemas:
DummyResponse:
required:
- status
type: object
properties:
status:
type: string
DummyRequest:
required:
- product_id
type: object
properties:
product_id:
type: string
locale:
type: string
default: "en_US"
Loading