Skip to content

Commit af87e8b

Browse files
committed
add support for auto-detecting x-spring-paginated in Spring Boot operations
1 parent 3331ddc commit af87e8b

1 file changed

Lines changed: 40 additions & 5 deletions

File tree

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

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.net.URL;
4646
import java.util.*;
4747
import java.util.regex.Matcher;
48+
import java.util.stream.Collectors;
4849

4950
import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER;
5051
import static org.openapitools.codegen.utils.StringUtils.camelize;
@@ -95,6 +96,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
9596
public static final String REQUEST_MAPPING_OPTION = "requestMappingMode";
9697
public static final String USE_REQUEST_MAPPING_ON_CONTROLLER = "useRequestMappingOnController";
9798
public static final String USE_REQUEST_MAPPING_ON_INTERFACE = "useRequestMappingOnInterface";
99+
public static final String AUTO_X_SPRING_PAGINATED = "autoXSpringPaginated";
98100

99101
@Getter
100102
public enum DeclarativeInterfaceReactiveMode {
@@ -158,6 +160,7 @@ public String getDescription() {
158160
@Setter private boolean beanQualifiers = false;
159161
@Setter private DeclarativeInterfaceReactiveMode declarativeInterfaceReactiveMode = DeclarativeInterfaceReactiveMode.coroutines;
160162
@Setter private boolean useResponseEntity = true;
163+
@Setter private boolean autoXSpringPaginated = false;
161164

162165
@Getter @Setter
163166
protected boolean useSpringBoot3 = false;
@@ -251,6 +254,7 @@ public KotlinSpringServerCodegen() {
251254
addOption(X_KOTLIN_IMPLEMENTS_FIELDS_SKIP, "A list of fields per schema name that should NOT be created with `override` keyword despite their presence in vendor extension `x-kotlin-implements-fields` for the schema. Example: yaml `xKotlinImplementsFieldsSkip: Pet: [photoUrls]` skips `override` for `photoUrls` in schema `Pet`", "empty map");
252255
addOption(SCHEMA_IMPLEMENTS, "A map of single interface or a list of interfaces per schema name that should be implemented (serves similar purpose as `x-kotlin-implements`, but is fully decoupled from the api spec). Example: yaml `schemaImplements: {Pet: com.some.pack.WithId, Category: [com.some.pack.CategoryInterface], Dog: [com.some.pack.Canine, com.some.pack.OtherInterface]}` implements interfaces in schemas `Pet` (interface `com.some.pack.WithId`), `Category` (interface `com.some.pack.CategoryInterface`), `Dog`(interfaces `com.some.pack.Canine`, `com.some.pack.OtherInterface`)", "empty map");
253256
addOption(SCHEMA_IMPLEMENTS_FIELDS, "A map of single field or a list of fields per schema name that should be prepended with `override` (serves similar purpose as `x-kotlin-implements-fields`, but is fully decoupled from the api spec). Example: yaml `schemaImplementsFields: {Pet: id, Category: [name, id], Dog: [bark, breed]}` marks fields to be prepended with `override` in schemas `Pet` (field `id`), `Category` (fields `name`, `id`) and `Dog` (fields `bark`, `breed`)", "empty map");
257+
addSwitch(AUTO_X_SPRING_PAGINATED, "Automatically add x-spring-paginated to operations that have 'page', 'size', and 'sort' query parameters. When enabled, operations with all three parameters will have Pageable support automatically applied. Operations with x-spring-paginated explicitly set to false will not be auto-detected.", autoXSpringPaginated);
254258
supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
255259
supportedLibraries.put(SPRING_CLOUD_LIBRARY,
256260
"Spring-Cloud-Feign client with Spring-Boot auto-configured settings.");
@@ -655,6 +659,10 @@ public void processOpts() {
655659
if (additionalProperties.containsKey(USE_TAGS)) {
656660
this.setUseTags(Boolean.parseBoolean(additionalProperties.get(USE_TAGS).toString()));
657661
}
662+
if (additionalProperties.containsKey(AUTO_X_SPRING_PAGINATED) && library.equals(SPRING_BOOT)) {
663+
this.setAutoXSpringPaginated(convertPropertyToBoolean(AUTO_X_SPRING_PAGINATED));
664+
}
665+
writePropertyBack(AUTO_X_SPRING_PAGINATED, autoXSpringPaginated);
658666
if (isUseSpringBoot3()) {
659667
if (DocumentationProvider.SPRINGFOX.equals(getDocumentationProvider())) {
660668
throw new IllegalArgumentException(DocumentationProvider.SPRINGFOX.getPropertyName() + " is not supported with Spring Boot > 3.x");
@@ -886,6 +894,12 @@ public void addOperationToGroup(String tag, String resourcePath, Operation opera
886894
* - Removes the default Spring Data Web pagination query parameters (page, size, sort)
887895
* - Adds appropriate imports (Pageable, ApiIgnore for springfox, ParameterObject for springdoc)
888896
*
897+
* Auto-detection (when autoXSpringPaginated is enabled):
898+
* - Automatically detects operations with 'page', 'size', and 'sort' query parameters (case-sensitive)
899+
* - Applies x-spring-paginated behavior to these operations automatically
900+
* - Respects manual x-spring-paginated: false setting (manual override takes precedence)
901+
* - Only applies when library is spring-boot
902+
*
889903
* Note: x-spring-paginated is ONLY applied for server-side libraries (spring-boot).
890904
* Client libraries (spring-cloud, spring-declarative-http-interface) need actual query parameters
891905
* to send over HTTP, so the extension is ignored for them.
@@ -905,7 +919,33 @@ public void addOperationToGroup(String tag, String resourcePath, Operation opera
905919
*/
906920
@Override
907921
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<io.swagger.v3.oas.models.servers.Server> servers) {
922+
// #8315 Spring Data Web default query params recognized by Pageable
923+
List<String> defaultPageableQueryParams = Arrays.asList("page", "size", "sort");
924+
908925
CodegenOperation codegenOperation = super.fromOperation(path, httpMethod, operation, servers);
926+
927+
// Auto-detect pagination parameters and add x-spring-paginated if autoXSpringPaginated is enabled
928+
// Only for spring-boot library, respect manual x-spring-paginated: false setting
929+
if (SPRING_BOOT.equals(library) && autoXSpringPaginated) {
930+
// Check if x-spring-paginated is not explicitly set to false
931+
if (operation.getExtensions() == null || !Boolean.FALSE.equals(operation.getExtensions().get("x-spring-paginated"))) {
932+
// Check if operation has all three pagination query parameters (case-sensitive)
933+
boolean hasParamsForPageable = codegenOperation.queryParams.stream()
934+
.map(p -> p.baseName)
935+
.collect(Collectors.toSet())
936+
.containsAll(defaultPageableQueryParams);
937+
938+
if (hasParamsForPageable) {
939+
// Automatically add x-spring-paginated to the operation
940+
if (operation.getExtensions() == null) {
941+
operation.setExtensions(new HashMap<>());
942+
}
943+
operation.getExtensions().put("x-spring-paginated", Boolean.TRUE);
944+
codegenOperation.vendorExtensions.put("x-spring-paginated", Boolean.TRUE);
945+
}
946+
}
947+
}
948+
909949
// Only process x-spring-paginated for server-side libraries (spring-boot)
910950
// Client libraries (spring-cloud, spring-declarative-http-interface) need actual query parameters for HTTP requests
911951
if (SPRING_BOOT.equals(library)) {
@@ -925,11 +965,6 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
925965
codegenOperation.imports.add("ParameterObject");
926966
}
927967

928-
// #8315 Spring Data Web default query params recognized by Pageable
929-
List<String> defaultPageableQueryParams = new ArrayList<>(
930-
Arrays.asList("page", "size", "sort")
931-
);
932-
933968
// #8315 Remove matching Spring Data Web default query params if 'x-spring-paginated' with Pageable is used
934969
codegenOperation.queryParams.removeIf(param -> defaultPageableQueryParams.contains(param.baseName));
935970
codegenOperation.allParams.removeIf(param -> param.isQueryParam && defaultPageableQueryParams.contains(param.baseName));

0 commit comments

Comments
 (0)