Skip to content

Commit fc10db4

Browse files
committed
support also list format
1 parent 69858d4 commit fc10db4

4 files changed

Lines changed: 65 additions & 6 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -966,13 +966,19 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
966966
if (DocumentationProvider.SPRINGDOC.equals(getDocumentationProvider())) {
967967
codegenOperation.imports.add("PageableAsQueryParam");
968968
// Prepend @PageableAsQueryParam to existing x-operation-extra-annotation if present
969+
// Use getObjectAsStringList to properly handle both list and string formats:
970+
// - YAML list: ['@Ann1', '@Ann2'] -> List of annotations
971+
// - Single string: '@Ann1 @Ann2' -> Single-element list
972+
// - Nothing/null -> Empty list
969973
Object existingAnnotation = codegenOperation.vendorExtensions.get("x-operation-extra-annotation");
970-
if (existingAnnotation != null && !existingAnnotation.toString().isEmpty()) {
971-
codegenOperation.vendorExtensions.put("x-operation-extra-annotation",
972-
"@PageableAsQueryParam\n " + existingAnnotation);
973-
} else {
974-
codegenOperation.vendorExtensions.put("x-operation-extra-annotation", "@PageableAsQueryParam");
975-
}
974+
List<String> annotations = DefaultCodegen.getObjectAsStringList(existingAnnotation);
975+
976+
// Prepend @PageableAsQueryParam to the beginning of the list
977+
List<String> updatedAnnotations = new ArrayList<>();
978+
updatedAnnotations.add("@PageableAsQueryParam");
979+
updatedAnnotations.addAll(annotations);
980+
981+
codegenOperation.vendorExtensions.put("x-operation-extra-annotation", updatedAnnotations);
976982
}
977983

978984
// #8315 Remove matching Spring Data Web default query params if 'x-spring-paginated' with Pageable is used
@@ -1228,6 +1234,7 @@ public List<VendorExtension> getSupportedVendorExtensions() {
12281234
extensions.add(VendorExtension.X_CONTENT_TYPE);
12291235
extensions.add(VendorExtension.X_DISCRIMINATOR_VALUE);
12301236
extensions.add(VendorExtension.X_FIELD_EXTRA_ANNOTATION);
1237+
extensions.add(VendorExtension.X_OPERATION_EXTRA_ANNOTATION);
12311238
extensions.add(VendorExtension.X_PATTERN_MESSAGE);
12321239
extensions.add(VendorExtension.X_SIZE_MESSAGE);
12331240
extensions.add(VendorExtension.X_MINIMUM_MESSAGE);

modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3961,6 +3961,54 @@ public void springPaginatedWithSpringDocPrependsToExistingAnnotation() throws Ex
39613961
assertFileContains(petApi.toPath(), "@Parameter(hidden = true) pageable: Pageable");
39623962
}
39633963

3964+
@Test
3965+
public void springPaginatedWithSpringDocPrependsToExistingAnnotationArray() throws Exception {
3966+
Map<String, Object> additionalProperties = new HashMap<>();
3967+
additionalProperties.put(USE_TAGS, "true");
3968+
additionalProperties.put(DOCUMENTATION_PROVIDER, "springdoc");
3969+
additionalProperties.put(INTERFACE_ONLY, "true");
3970+
additionalProperties.put(SKIP_DEFAULT_INTERFACE, "true");
3971+
3972+
Map<String, File> files = generateFromContract("src/test/resources/3_0/spring/petstore-with-spring-pageable.yaml", additionalProperties);
3973+
3974+
File petApi = files.get("PetApi.kt");
3975+
String content = Files.readString(petApi.toPath());
3976+
3977+
// Verify that PageableAsQueryParam is imported
3978+
assertFileContains(petApi.toPath(), "import org.springdoc.core.converters.models.PageableAsQueryParam");
3979+
3980+
// Find the findPetsByStatus method
3981+
int findPetsByStatusStart = content.indexOf("fun findPetsByStatus(");
3982+
Assert.assertTrue(findPetsByStatusStart > 0, "findPetsByStatus method should exist");
3983+
3984+
// Check the annotations appear before the method in the correct order
3985+
String methodBlock = content.substring(Math.max(0, findPetsByStatusStart - 1500), findPetsByStatusStart);
3986+
3987+
int pageableAsQueryParamPos = methodBlock.lastIndexOf("@PageableAsQueryParam");
3988+
int validatedPos = methodBlock.lastIndexOf("@org.springframework.validation.annotation.Validated");
3989+
int preAuthorizePos = methodBlock.lastIndexOf("@org.springframework.security.access.prepost.PreAuthorize");
3990+
int requestMappingPos = methodBlock.lastIndexOf("@RequestMapping");
3991+
3992+
Assert.assertTrue(pageableAsQueryParamPos > 0, "@PageableAsQueryParam should be present before findPetsByStatus method");
3993+
Assert.assertTrue(validatedPos > 0, "@Validated should be present before findPetsByStatus method");
3994+
Assert.assertTrue(preAuthorizePos > 0, "@PreAuthorize should be present before findPetsByStatus method");
3995+
3996+
// Verify @PageableAsQueryParam comes first (prepended to the array)
3997+
Assert.assertTrue(pageableAsQueryParamPos < validatedPos,
3998+
"@PageableAsQueryParam should be prepended (appear before) @Validated annotation");
3999+
4000+
// Verify the original array order is preserved after @PageableAsQueryParam
4001+
Assert.assertTrue(validatedPos < preAuthorizePos,
4002+
"@Validated should appear before @PreAuthorize (original array order preserved)");
4003+
4004+
// Verify all annotations come before @RequestMapping
4005+
Assert.assertTrue(preAuthorizePos < requestMappingPos,
4006+
"All annotations should appear before @RequestMapping");
4007+
4008+
// Verify the Pageable parameter still has @Parameter(hidden = true)
4009+
assertFileContains(petApi.toPath(), "@Parameter(hidden = true) pageable: Pageable");
4010+
}
4011+
39644012
@Test
39654013
public void springPaginatedMixedOperations() throws Exception {
39664014
Map<String, Object> additionalProperties = new HashMap<>();

modules/openapi-generator/src/test/resources/3_0/spring/petstore-with-spring-pageable.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ paths:
117117
- write:pets
118118
- read:pets
119119
x-spring-paginated: true
120+
x-operation-extra-annotation:
121+
- "@org.springframework.validation.annotation.Validated"
122+
- "@org.springframework.security.access.prepost.PreAuthorize(\"hasRole('ADMIN')\")"
120123
/pet/findByTags:
121124
get:
122125
tags:

samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/api/PetApi.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ ResponseEntity<Pet> getPetById(
239239
value = PetApi.PATH_LIST_ALL_PETS,
240240
produces = { "application/json", "application/xml" }
241241
)
242+
@org.springframework.validation.annotation.Validated
242243
ResponseEntity<List<Pet>> listAllPets(
243244
@ParameterObject final Pageable pageable
244245
);

0 commit comments

Comments
 (0)