Skip to content

Commit 69858d4

Browse files
committed
make sure the PageableAsQueryParam does not remove already present x-operation-extra-annotation content
1 parent 4aadf0f commit 69858d4

3 files changed

Lines changed: 52 additions & 1 deletion

File tree

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,14 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
965965
}
966966
if (DocumentationProvider.SPRINGDOC.equals(getDocumentationProvider())) {
967967
codegenOperation.imports.add("PageableAsQueryParam");
968-
codegenOperation.vendorExtensions.put("x-operation-extra-annotation", "@PageableAsQueryParam");
968+
// Prepend @PageableAsQueryParam to existing x-operation-extra-annotation if present
969+
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+
}
969976
}
970977

971978
// #8315 Remove matching Spring Data Web default query params if 'x-spring-paginated' with Pageable is used

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3918,6 +3918,49 @@ public void springPaginatedNoParamsNoContext() throws Exception {
39183918
assertFileContains(petApi.toPath(), "fun listAllPets(@Parameter(hidden = true) pageable: Pageable)");
39193919
}
39203920

3921+
@Test
3922+
public void springPaginatedWithSpringDocPrependsToExistingAnnotation() throws Exception {
3923+
Map<String, Object> additionalProperties = new HashMap<>();
3924+
additionalProperties.put(USE_TAGS, "true");
3925+
additionalProperties.put(DOCUMENTATION_PROVIDER, "springdoc");
3926+
additionalProperties.put(INTERFACE_ONLY, "true");
3927+
additionalProperties.put(SKIP_DEFAULT_INTERFACE, "true");
3928+
3929+
Map<String, File> files = generateFromContract("src/test/resources/3_0/spring/petstore-with-spring-pageable.yaml", additionalProperties);
3930+
3931+
File petApi = files.get("PetApi.kt");
3932+
String content = Files.readString(petApi.toPath());
3933+
3934+
// Verify that both annotations are imported
3935+
assertFileContains(petApi.toPath(), "import org.springdoc.core.converters.models.PageableAsQueryParam");
3936+
assertFileContains(petApi.toPath(), "import org.springframework.validation.annotation.Validated");
3937+
3938+
// Find the listAllPets method
3939+
int listAllPetsStart = content.indexOf("fun listAllPets(");
3940+
Assert.assertTrue(listAllPetsStart > 0, "listAllPets method should exist");
3941+
3942+
// Check the annotations appear before the method in the correct order
3943+
String methodBlock = content.substring(Math.max(0, listAllPetsStart - 1000), listAllPetsStart);
3944+
3945+
int pageableAsQueryParamPos = methodBlock.lastIndexOf("@PageableAsQueryParam");
3946+
int validatedPos = methodBlock.lastIndexOf("@org.springframework.validation.annotation.Validated");
3947+
int requestMappingPos = methodBlock.lastIndexOf("@RequestMapping");
3948+
3949+
Assert.assertTrue(pageableAsQueryParamPos > 0, "@PageableAsQueryParam should be present before listAllPets method");
3950+
Assert.assertTrue(validatedPos > 0, "@Validated should be present before listAllPets method");
3951+
3952+
// Verify @PageableAsQueryParam comes before @Validated (prepended)
3953+
Assert.assertTrue(pageableAsQueryParamPos < validatedPos,
3954+
"@PageableAsQueryParam should be prepended (appear before) existing @Validated annotation");
3955+
3956+
// Verify both annotations come before @RequestMapping
3957+
Assert.assertTrue(validatedPos < requestMappingPos,
3958+
"Both annotations should appear before @RequestMapping");
3959+
3960+
// Verify the Pageable parameter still has @Parameter(hidden = true)
3961+
assertFileContains(petApi.toPath(), "@Parameter(hidden = true) pageable: Pageable");
3962+
}
3963+
39213964
@Test
39223965
public void springPaginatedMixedOperations() throws Exception {
39233966
Map<String, Object> additionalProperties = new HashMap<>();

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ paths:
243243
- write:pets
244244
- read:pets
245245
x-spring-paginated: true
246+
x-operation-extra-annotation: "@org.springframework.validation.annotation.Validated" # test that the annotation is preserved when x-spring-paginated:true is used and is prepended with the @PageableAsQueryParam for springdoc
246247
/pet/{petId}:
247248
get:
248249
tags:

0 commit comments

Comments
 (0)