From f7c827a826cef2e4bc8fb5e6b72f7b9d07616631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Metli=C4=8Dka?= Date: Tue, 21 Apr 2026 15:14:09 +0200 Subject: [PATCH 1/6] fix(spring): ensure PagedModel uses mapped FQN for item type in code generation fix(spring): enhance PagedModel handling with import mapping and schema mapping support --- .../languages/KotlinSpringServerCodegen.java | 28 +++++++--- .../codegen/languages/SpringCodegen.java | 28 +++++++--- .../java/spring/SpringCodegenTest.java | 51 +++++++++++++++++++ .../spring/KotlinSpringServerCodegenTest.java | 38 ++++++++++++++ 4 files changed, 131 insertions(+), 14 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java index 9c1e9478b7ec..24926db965e9 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java @@ -200,6 +200,8 @@ public String getDescription() { // Map from schema name to detected paged-model info (populated when substituteGenericPagedModel=true) private Map pagedModelRegistry = new HashMap<>(); + // Simple class name of the PagedModel substitute (derived from importMapping; defaults to "PagedModel") + private String pagedModelClassName = "PagedModel"; public KotlinSpringServerCodegen() { super(); @@ -1142,21 +1144,24 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation pagedModelRegistry.get(codegenOperation.returnBaseType); if (detected != null) { String oldType = codegenOperation.returnType; - String newBaseType = "PagedModel<" + detected.itemSchemaName + ">"; + // Run through toModelName so that schemaMappings (e.g. User → com.example.MyUser) + // are honored: the mapped name is used both in the type arg and for import resolution. + String itemType = toModelName(detected.itemSchemaName); + String newBaseType = pagedModelClassName + "<" + itemType + ">"; codegenOperation.returnType = newBaseType; - codegenOperation.returnBaseType = "PagedModel"; + codegenOperation.returnBaseType = pagedModelClassName; // Clear any container flag — PagedModel is not itself a List/array codegenOperation.returnContainer = null; - // Add item type import (needed for PagedModel in method signature) - codegenOperation.imports.add(detected.itemSchemaName); - codegenOperation.imports.add("PagedModel"); + // Add item type import (needed for PagedModel in method signature) + codegenOperation.imports.add(itemType); + codegenOperation.imports.add(pagedModelClassName); // Remove paged schema import when no annotations are generated — // the class is suppressed and not referenced anywhere if (getAnnotationLibrary() == AnnotationLibrary.NONE) { codegenOperation.imports.remove(detected.schemaName); } - LOGGER.info("substituteGenericPagedModel: operation '{}': replacing return type '{}' with PagedModel<{}>", - codegenOperation.operationId, oldType, detected.itemSchemaName); + LOGGER.info("substituteGenericPagedModel: operation '{}': replacing return type '{}' with {}<{}>", + codegenOperation.operationId, oldType, pagedModelClassName, itemType); } } @@ -1203,6 +1208,15 @@ public void preprocessOpenAPI(OpenAPI openAPI) { pagedModelRegistry = PagedModelScanUtils.scanPagedModels(openAPI); if (!pagedModelRegistry.isEmpty()) { importMapping.putIfAbsent("PagedModel", "org.springframework.data.web.PagedModel"); + // Derive the actual simple class name from the FQN in importMapping so that a + // custom mapping (e.g. "PagedModel" → "com.example.MyPagedModel") is respected. + // The simple name of the FQN becomes the token used in generated code, and is + // registered in importMapping so that template import resolution works. + String fqn = importMapping.get("PagedModel"); + pagedModelClassName = fqn.substring(fqn.lastIndexOf('.') + 1); + if (!pagedModelClassName.equals("PagedModel")) { + importMapping.put(pagedModelClassName, fqn); + } LOGGER.info("substituteGenericPagedModel: detected {} paged-model schema(s): {}", pagedModelRegistry.size(), pagedModelRegistry.keySet()); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java index 81e1bb177c01..c7433d103859 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java @@ -203,6 +203,8 @@ public enum RequestMappingMode { private Map pageableConstraintsRegistry = new HashMap<>(); // Map from schema name to detected paged-model info (populated when substituteGenericPagedModel=true) private Map pagedModelRegistry = new HashMap<>(); + // Simple class name of the PagedModel substitute (derived from importMapping; defaults to "PagedModel") + private String pagedModelClassName = "PagedModel"; public SpringCodegen() { super(); @@ -871,6 +873,15 @@ public void preprocessOpenAPI(OpenAPI openAPI) { pagedModelRegistry = PagedModelScanUtils.scanPagedModels(openAPI); if (!pagedModelRegistry.isEmpty()) { importMapping.putIfAbsent("PagedModel", "org.springframework.data.web.PagedModel"); + // Derive the actual simple class name from the FQN in importMapping so that a + // custom mapping (e.g. "PagedModel" → "com.example.MyPagedModel") is respected. + // The simple name of the FQN becomes the token used in generated code, and is + // registered in importMapping so that template import resolution works. + String fqn = importMapping.get("PagedModel"); + pagedModelClassName = fqn.substring(fqn.lastIndexOf('.') + 1); + if (!pagedModelClassName.equals("PagedModel")) { + importMapping.put(pagedModelClassName, fqn); + } LOGGER.info("substituteGenericPagedModel: detected {} paged-model schema(s): {}", pagedModelRegistry.size(), pagedModelRegistry.keySet()); } @@ -1352,21 +1363,24 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation pagedModelRegistry.get(codegenOperation.returnBaseType); if (detected != null) { String oldType = codegenOperation.returnType; - String newBaseType = "PagedModel<" + detected.itemSchemaName + ">"; + // Run through toModelName so that schemaMappings (e.g. User → com.example.MyUser) + // are honored: the mapped name is used both in the type arg and for import resolution. + String itemType = toModelName(detected.itemSchemaName); + String newBaseType = pagedModelClassName + "<" + itemType + ">"; codegenOperation.returnType = newBaseType; - codegenOperation.returnBaseType = "PagedModel"; + codegenOperation.returnBaseType = pagedModelClassName; // Clear any container flag — PagedModel is not itself a List/array codegenOperation.returnContainer = null; - // Add item type import (needed for PagedModel in method signature) - codegenOperation.imports.add(detected.itemSchemaName); - codegenOperation.imports.add("PagedModel"); + // Add item type import (needed for PagedModel in method signature) + codegenOperation.imports.add(itemType); + codegenOperation.imports.add(pagedModelClassName); // Remove paged schema import when no annotations are generated — // the class is suppressed and not referenced anywhere if (getAnnotationLibrary() == AnnotationLibrary.NONE) { codegenOperation.imports.remove(detected.schemaName); } - LOGGER.info("substituteGenericPagedModel: operation '{}': replacing return type '{}' with PagedModel<{}>", - codegenOperation.operationId, oldType, detected.itemSchemaName); + LOGGER.info("substituteGenericPagedModel: operation '{}': replacing return type '{}' with {}<{}>", + codegenOperation.operationId, oldType, pagedModelClassName, itemType); } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java index 58feb32a3b25..fe0cc2a73d28 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java @@ -7302,4 +7302,55 @@ public void substituteGenericPagedModel_suppressesPageMetaWhenNoAnnotations() th // PageMeta is referenced by SearchResult (a non-paged schema) → must be kept assertThat(files).containsKey("PageMeta.java"); } + + @Test + public void substituteGenericPagedModel_respectsSchemaMappingForItemType() throws IOException { + // When the item schema (User) is mapped to an external FQN via schemaMappings, + // the PagedModel type arg must use the mapped FQN, not the raw schema name. + Map props = commonPagedModelProps(); + + Map files = generateFromContract( + "src/test/resources/3_0/spring/petstore-paged-model.yaml", SPRING_BOOT, props, + configurator -> configurator.addSchemaMapping("User", "com.example.external.ExternalUser")); + + JavaFileAssert.assertThat(files.get("UserApi.java")) + .assertMethod("listUsers") + .hasReturnType("ResponseEntity>"); + } + + @Test + public void substituteGenericPagedModel_respectsSchemaMappingWithImportMappingForItemType() throws IOException { + // When the item schema (User) is mapped to an external FQN via schemaMappings, + // the PagedModel type arg must use the mapped FQN, not the raw schema name. + Map props = commonPagedModelProps(); + + Map files = generateFromContract( + "src/test/resources/3_0/spring/petstore-paged-model.yaml", SPRING_BOOT, props, + configurator -> configurator + .addSchemaMapping("User", "ExternalUser") + .addImportMapping("ExternalUser", "com.example.external.ExternalUser")); + + JavaFileAssert.assertThat(files.get("UserApi.java")) + .hasImports("com.example.external.ExternalUser") + .assertMethod("listUsers") + .hasReturnType("ResponseEntity>"); + } + + @Test + public void substituteGenericPagedModel_respectsCustomImportMappingClassName() throws IOException { + // When the user remaps "PagedModel" to a FQN with a different simple class name, + // the generated code must use that simple name (not "PagedModel") as the type token + // and emit the correct import for the custom FQN. + Map props = commonPagedModelProps(); + + Map files = generateFromContract( + "src/test/resources/3_0/spring/petstore-paged-model.yaml", SPRING_BOOT, props, + configurator -> configurator + .addImportMapping("PagedModel", "com.example.custom.MyPagedModel")); + + JavaFileAssert.assertThat(files.get("UserApi.java")) + .hasImports("com.example.custom.MyPagedModel") + .assertMethod("listUsers") + .hasReturnType("ResponseEntity>"); + } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java index 26d46750c015..5eb1554fdb55 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java @@ -5662,4 +5662,42 @@ public void substituteGenericPagedModel_suppressesPageMetaWhenNoAnnotations() th // PageMeta is referenced by SearchResult (a non-paged schema) → must be kept assertThat(files).containsKey("PageMeta.kt"); } + + @Test + public void substituteGenericPagedModel_respectsSchemaMappingForItemType() throws IOException { + // When the item schema (User) is mapped to an external FQN via schemaMappings, + // the PagedModel type arg must use the mapped FQN, not the raw schema name. + Map files = generateFromContract( + "src/test/resources/3_0/spring/petstore-paged-model.yaml", + commonKotlinPagedModelProps(), + new HashMap<>(), + configurator -> configurator.addSchemaMapping("User", "com.example.external.ExternalUser")); + + File userApi = files.get("UserApi.kt"); + assertThat(userApi).isNotNull(); + String content = Files.readString(userApi.toPath()); + // Return type must use the schema-mapped FQN, not the raw schema name + assertThat(content).contains("PagedModel"); + // toModelImport of a dotted name returns the FQN as-is → correct import + assertThat(content).contains("import com.example.external.ExternalUser"); + } + + @Test + public void substituteGenericPagedModel_respectsCustomImportMappingClassName() throws IOException { + // When the user remaps "PagedModel" to a FQN with a different simple class name, + // the generated code must use that simple name (not "PagedModel") as the type token + // and emit the correct import for the custom FQN. + Map files = generateFromContract( + "src/test/resources/3_0/spring/petstore-paged-model.yaml", + commonKotlinPagedModelProps(), + new HashMap<>(), + configurator -> configurator + .addImportMapping("PagedModel", "com.example.custom.MyPagedModel")); + + File userApi = files.get("UserApi.kt"); + assertThat(userApi).isNotNull(); + String content = Files.readString(userApi.toPath()); + assertThat(content).contains("MyPagedModel"); + assertThat(content).contains("import com.example.custom.MyPagedModel"); + } } From 42bd4e173fe6c4090e3ef7f0d76fb3447e73dec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Metli=C4=8Dka?= Date: Tue, 21 Apr 2026 15:39:55 +0200 Subject: [PATCH 2/6] fix(spring): generate supporting PagedModel files in config package (can be replaced with custom one via importMapping) --- .../languages/KotlinSpringServerCodegen.java | 8 +- .../codegen/languages/SpringCodegen.java | 8 +- .../resources/JavaSpring/pagedModel.mustache | 95 +++++++++++++++++++ .../kotlin-spring/pagedModel.mustache | 27 ++++++ .../java/spring/SpringCodegenTest.java | 24 ++++- .../spring/KotlinSpringServerCodegenTest.java | 23 ++++- 6 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/JavaSpring/pagedModel.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/pagedModel.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java index 24926db965e9..2afa55b8aa9e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java @@ -1207,7 +1207,13 @@ public void preprocessOpenAPI(OpenAPI openAPI) { if (SPRING_BOOT.equals(library) && substituteGenericPagedModel) { pagedModelRegistry = PagedModelScanUtils.scanPagedModels(openAPI); if (!pagedModelRegistry.isEmpty()) { - importMapping.putIfAbsent("PagedModel", "org.springframework.data.web.PagedModel"); + boolean customMapping = importMapping.containsKey("PagedModel"); + importMapping.putIfAbsent("PagedModel", configPackage + ".PagedModel"); + if (!customMapping) { + // No custom class provided — generate the simple PagedModel into the config package. + supportingFiles.add(new SupportingFile("pagedModel.mustache", + (sourceFolder + File.separator + configPackage).replace(".", File.separator), "PagedModel.kt")); + } // Derive the actual simple class name from the FQN in importMapping so that a // custom mapping (e.g. "PagedModel" → "com.example.MyPagedModel") is respected. // The simple name of the FQN becomes the token used in generated code, and is diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java index c7433d103859..0eb0e9ed36dd 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java @@ -872,7 +872,13 @@ public void preprocessOpenAPI(OpenAPI openAPI) { if (SPRING_BOOT.equals(library) && substituteGenericPagedModel) { pagedModelRegistry = PagedModelScanUtils.scanPagedModels(openAPI); if (!pagedModelRegistry.isEmpty()) { - importMapping.putIfAbsent("PagedModel", "org.springframework.data.web.PagedModel"); + boolean customMapping = importMapping.containsKey("PagedModel"); + importMapping.putIfAbsent("PagedModel", configPackage + ".PagedModel"); + if (!customMapping) { + // No custom class provided — generate the simple PagedModel into the config package. + supportingFiles.add(new SupportingFile("pagedModel.mustache", + (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "PagedModel.java")); + } // Derive the actual simple class name from the FQN in importMapping so that a // custom mapping (e.g. "PagedModel" → "com.example.MyPagedModel") is respected. // The simple name of the FQN becomes the token used in generated code, and is diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/pagedModel.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/pagedModel.mustache new file mode 100644 index 000000000000..7bf2059aae37 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/JavaSpring/pagedModel.mustache @@ -0,0 +1,95 @@ +package {{configPackage}}; + +import java.util.List; + +/** + * Simple generic paged response wrapper generated by openapi-generator. + * + *

Holds a page of content items and pagination metadata. Jackson deserializes this from the + * standard Spring {@code Page} JSON shape: + *

+ * {
+ *   "content": [...],
+ *   "page": { "size": 20, "totalElements": 100, "totalPages": 5, "number": 0 }
+ * }
+ * 
+ * + *

To use your own class instead, set {@code importMappings.PagedModel} in the generator config. + */ +public class PagedModel { + + private List content; + private PageMetadata page; + + public PagedModel() {} + + public PagedModel(List content, PageMetadata page) { + this.content = content; + this.page = page; + } + + public List getContent() { + return content; + } + + public void setContent(List content) { + this.content = content; + } + + public PageMetadata getPage() { + return page; + } + + public void setPage(PageMetadata page) { + this.page = page; + } + + public static class PageMetadata { + + private long size; + private long totalElements; + private long totalPages; + private long number; + + public PageMetadata() {} + + public PageMetadata(long size, long totalElements, long totalPages, long number) { + this.size = size; + this.totalElements = totalElements; + this.totalPages = totalPages; + this.number = number; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public long getTotalElements() { + return totalElements; + } + + public void setTotalElements(long totalElements) { + this.totalElements = totalElements; + } + + public long getTotalPages() { + return totalPages; + } + + public void setTotalPages(long totalPages) { + this.totalPages = totalPages; + } + + public long getNumber() { + return number; + } + + public void setNumber(long number) { + this.number = number; + } + } +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/pagedModel.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/pagedModel.mustache new file mode 100644 index 000000000000..02aee68605b0 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/pagedModel.mustache @@ -0,0 +1,27 @@ +package {{configPackage}} + +/** + * Simple generic paged response wrapper generated by openapi-generator. + * + * Holds a page of content items and pagination metadata. Jackson deserializes this from the + * standard Spring `Page` JSON shape: + * ```json + * { + * "content": [...], + * "page": { "size": 20, "totalElements": 100, "totalPages": 5, "number": 0 } + * } + * ``` + * + * To use your own class instead, set `importMappings.PagedModel` in the generator config. + */ +data class PagedModel( + val content: List, + val page: PageMetadata, +) { + data class PageMetadata( + val size: Long, + val totalElements: Long, + val totalPages: Long, + val number: Long, + ) +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java index fe0cc2a73d28..10619278e3a8 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java @@ -7242,9 +7242,9 @@ public void substituteGenericPagedModel_importsPagedModelAndItemTypeInApiFile() Map files = generateFromContract( "src/test/resources/3_0/spring/petstore-paged-model.yaml", SPRING_BOOT, props); - // The api file must import both PagedModel and the item type + // The api file must import both the generated PagedModel and the item type JavaFileAssert.assertThat(files.get("UserApi.java")) - .fileContains("import org.springframework.data.web.PagedModel") + .fileContains("import org.openapitools.configuration.PagedModel") .fileContains("import org.openapitools.model.User"); } @@ -7336,6 +7336,26 @@ public void substituteGenericPagedModel_respectsSchemaMappingWithImportMappingFo .hasReturnType("ResponseEntity>"); } + @Test + public void substituteGenericPagedModel_generatesPagedModelSupportingFile() throws IOException { + Map files = generateFromContract( + "src/test/resources/3_0/spring/petstore-paged-model.yaml", SPRING_BOOT, commonPagedModelProps()); + + assertThat(files).containsKey("PagedModel.java"); + } + + @Test + public void substituteGenericPagedModel_doesNotGeneratePagedModelFileWhenCustomMapping() throws IOException { + Map props = commonPagedModelProps(); + + Map files = generateFromContract( + "src/test/resources/3_0/spring/petstore-paged-model.yaml", SPRING_BOOT, props, + configurator -> configurator + .addImportMapping("PagedModel", "com.example.custom.MyPagedModel")); + + assertThat(files).doesNotContainKey("PagedModel.java"); + } + @Test public void substituteGenericPagedModel_respectsCustomImportMappingClassName() throws IOException { // When the user remaps "PagedModel" to a FQN with a different simple class name, diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java index 5eb1554fdb55..4183e1cdd027 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java @@ -5604,7 +5604,8 @@ public void substituteGenericPagedModel_importsPagedModelAndItemTypeInApiFile() File userApi = files.get("UserApi.kt"); assertThat(userApi).isNotNull(); String content = Files.readString(userApi.toPath()); - assertThat(content).contains("import org.springframework.data.web.PagedModel"); + // The api file must import the generated PagedModel and the item type + assertThat(content).contains("import org.openapitools.configuration.PagedModel"); assertThat(content).contains("import org.openapitools.model.User"); } @@ -5682,6 +5683,26 @@ public void substituteGenericPagedModel_respectsSchemaMappingForItemType() throw assertThat(content).contains("import com.example.external.ExternalUser"); } + @Test + public void substituteGenericPagedModel_generatesPagedModelSupportingFile() throws IOException { + Map files = generateFromContract( + "src/test/resources/3_0/spring/petstore-paged-model.yaml", commonKotlinPagedModelProps()); + + assertThat(files).containsKey("PagedModel.kt"); + } + + @Test + public void substituteGenericPagedModel_doesNotGeneratePagedModelFileWhenCustomMapping() throws IOException { + Map files = generateFromContract( + "src/test/resources/3_0/spring/petstore-paged-model.yaml", + commonKotlinPagedModelProps(), + new HashMap<>(), + configurator -> configurator + .addImportMapping("PagedModel", "com.example.custom.MyPagedModel")); + + assertThat(files).doesNotContainKey("PagedModel.kt"); + } + @Test public void substituteGenericPagedModel_respectsCustomImportMappingClassName() throws IOException { // When the user remaps "PagedModel" to a FQN with a different simple class name, From 5780ef7ef10e6256db56cc72b59ce9bd22518d4a Mon Sep 17 00:00:00 2001 From: Jachym Metlicka Date: Tue, 21 Apr 2026 15:45:31 +0200 Subject: [PATCH 3/6] update samples --- .../.openapi-generator/FILES | 1 + .../kotlin/org/openapitools/api/OrderApi.kt | 2 +- .../kotlin/org/openapitools/api/PetApi.kt | 2 +- .../kotlin/org/openapitools/api/UserApi.kt | 2 +- .../openapitools/configuration/PagedModel.kt | 27 ++++++ .../.openapi-generator/FILES | 1 + .../java/org/openapitools/api/OrderApi.java | 2 +- .../java/org/openapitools/api/PetApi.java | 2 +- .../java/org/openapitools/api/UserApi.java | 2 +- .../configuration/PagedModel.java | 95 +++++++++++++++++++ 10 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/configuration/PagedModel.kt create mode 100644 samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/configuration/PagedModel.java diff --git a/samples/server/petstore/kotlin-springboot-paged-model/.openapi-generator/FILES b/samples/server/petstore/kotlin-springboot-paged-model/.openapi-generator/FILES index b3da4fa290fd..cf18998de776 100644 --- a/samples/server/petstore/kotlin-springboot-paged-model/.openapi-generator/FILES +++ b/samples/server/petstore/kotlin-springboot-paged-model/.openapi-generator/FILES @@ -12,6 +12,7 @@ src/main/kotlin/org/openapitools/api/OrderApi.kt src/main/kotlin/org/openapitools/api/PetApi.kt src/main/kotlin/org/openapitools/api/UserApi.kt src/main/kotlin/org/openapitools/configuration/EnumConverterConfiguration.kt +src/main/kotlin/org/openapitools/configuration/PagedModel.kt src/main/kotlin/org/openapitools/model/Order.kt src/main/kotlin/org/openapitools/model/PageMeta.kt src/main/kotlin/org/openapitools/model/Pet.kt diff --git a/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/OrderApi.kt b/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/OrderApi.kt index 118371deeb4d..632eb07d8d8d 100644 --- a/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/OrderApi.kt +++ b/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/OrderApi.kt @@ -6,7 +6,7 @@ package org.openapitools.api import org.openapitools.model.Order -import org.springframework.data.web.PagedModel +import org.openapitools.configuration.PagedModel import org.springframework.http.HttpStatus import org.springframework.http.MediaType import org.springframework.http.ResponseEntity diff --git a/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/PetApi.kt b/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/PetApi.kt index 0e79a47e5f4c..ca0a0f67d9ce 100644 --- a/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/PetApi.kt +++ b/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/PetApi.kt @@ -5,7 +5,7 @@ */ package org.openapitools.api -import org.springframework.data.web.PagedModel +import org.openapitools.configuration.PagedModel import org.openapitools.model.Pet import org.openapitools.model.SearchResult import org.springframework.http.HttpStatus diff --git a/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/UserApi.kt b/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/UserApi.kt index bdcd87592940..4361b508a781 100644 --- a/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/UserApi.kt +++ b/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/api/UserApi.kt @@ -5,7 +5,7 @@ */ package org.openapitools.api -import org.springframework.data.web.PagedModel +import org.openapitools.configuration.PagedModel import org.openapitools.model.User import org.openapitools.model.UserList import org.springframework.http.HttpStatus diff --git a/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/configuration/PagedModel.kt b/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/configuration/PagedModel.kt new file mode 100644 index 000000000000..7a67cb221720 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-paged-model/src/main/kotlin/org/openapitools/configuration/PagedModel.kt @@ -0,0 +1,27 @@ +package org.openapitools.configuration + +/** + * Simple generic paged response wrapper generated by openapi-generator. + * + * Holds a page of content items and pagination metadata. Jackson deserializes this from the + * standard Spring `Page` JSON shape: + * ```json + * { + * "content": [...], + * "page": { "size": 20, "totalElements": 100, "totalPages": 5, "number": 0 } + * } + * ``` + * + * To use your own class instead, set `importMappings.PagedModel` in the generator config. + */ +data class PagedModel( + val content: List, + val page: PageMetadata, +) { + data class PageMetadata( + val size: Long, + val totalElements: Long, + val totalPages: Long, + val number: Long, + ) +} diff --git a/samples/server/petstore/springboot-paged-model/.openapi-generator/FILES b/samples/server/petstore/springboot-paged-model/.openapi-generator/FILES index e30215256f5e..e51fe865d3ac 100644 --- a/samples/server/petstore/springboot-paged-model/.openapi-generator/FILES +++ b/samples/server/petstore/springboot-paged-model/.openapi-generator/FILES @@ -5,6 +5,7 @@ src/main/java/org/openapitools/api/OrderApi.java src/main/java/org/openapitools/api/PetApi.java src/main/java/org/openapitools/api/UserApi.java src/main/java/org/openapitools/configuration/EnumConverterConfiguration.java +src/main/java/org/openapitools/configuration/PagedModel.java src/main/java/org/openapitools/model/Order.java src/main/java/org/openapitools/model/PageMeta.java src/main/java/org/openapitools/model/Pet.java diff --git a/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/OrderApi.java b/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/OrderApi.java index 9fed008db18a..ab356fab0377 100644 --- a/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/OrderApi.java +++ b/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/OrderApi.java @@ -7,7 +7,7 @@ import org.springframework.lang.Nullable; import org.openapitools.model.Order; -import org.springframework.data.web.PagedModel; +import org.openapitools.configuration.PagedModel; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; diff --git a/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/PetApi.java b/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/PetApi.java index d60b776f61d9..38f1cb067fc8 100644 --- a/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/PetApi.java +++ b/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/PetApi.java @@ -6,7 +6,7 @@ package org.openapitools.api; import org.springframework.lang.Nullable; -import org.springframework.data.web.PagedModel; +import org.openapitools.configuration.PagedModel; import org.openapitools.model.Pet; import org.openapitools.model.SearchResult; import org.springframework.http.ResponseEntity; diff --git a/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/UserApi.java b/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/UserApi.java index 6d6429c0c32d..774dd92d1728 100644 --- a/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/UserApi.java +++ b/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/api/UserApi.java @@ -6,7 +6,7 @@ package org.openapitools.api; import org.springframework.lang.Nullable; -import org.springframework.data.web.PagedModel; +import org.openapitools.configuration.PagedModel; import org.openapitools.model.User; import org.openapitools.model.UserList; import org.springframework.http.ResponseEntity; diff --git a/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/configuration/PagedModel.java b/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/configuration/PagedModel.java new file mode 100644 index 000000000000..cebb0f6ce284 --- /dev/null +++ b/samples/server/petstore/springboot-paged-model/src/main/java/org/openapitools/configuration/PagedModel.java @@ -0,0 +1,95 @@ +package org.openapitools.configuration; + +import java.util.List; + +/** + * Simple generic paged response wrapper generated by openapi-generator. + * + *

Holds a page of content items and pagination metadata. Jackson deserializes this from the + * standard Spring {@code Page} JSON shape: + *

+ * {
+ *   "content": [...],
+ *   "page": { "size": 20, "totalElements": 100, "totalPages": 5, "number": 0 }
+ * }
+ * 
+ * + *

To use your own class instead, set {@code importMappings.PagedModel} in the generator config. + */ +public class PagedModel { + + private List content; + private PageMetadata page; + + public PagedModel() {} + + public PagedModel(List content, PageMetadata page) { + this.content = content; + this.page = page; + } + + public List getContent() { + return content; + } + + public void setContent(List content) { + this.content = content; + } + + public PageMetadata getPage() { + return page; + } + + public void setPage(PageMetadata page) { + this.page = page; + } + + public static class PageMetadata { + + private long size; + private long totalElements; + private long totalPages; + private long number; + + public PageMetadata() {} + + public PageMetadata(long size, long totalElements, long totalPages, long number) { + this.size = size; + this.totalElements = totalElements; + this.totalPages = totalPages; + this.number = number; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public long getTotalElements() { + return totalElements; + } + + public void setTotalElements(long totalElements) { + this.totalElements = totalElements; + } + + public long getTotalPages() { + return totalPages; + } + + public void setTotalPages(long totalPages) { + this.totalPages = totalPages; + } + + public long getNumber() { + return number; + } + + public void setNumber(long number) { + this.number = number; + } + } +} From c837967e238efe524ade4226ef7a98da406d6483 Mon Sep 17 00:00:00 2001 From: Jachym Metlicka Date: Tue, 21 Apr 2026 16:46:02 +0200 Subject: [PATCH 4/6] update documentation --- docs/generators/java-camel.md | 2 +- docs/generators/kotlin-spring.md | 2 +- docs/generators/spring.md | 2 +- .../codegen/languages/KotlinSpringServerCodegen.java | 4 ++-- .../org/openapitools/codegen/languages/SpringCodegen.java | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/generators/java-camel.md b/docs/generators/java-camel.md index 1bef17ecf9c2..72b9f8e0a2ff 100644 --- a/docs/generators/java-camel.md +++ b/docs/generators/java-camel.md @@ -104,7 +104,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| |springApiVersion|Value for 'version' attribute in @RequestMapping (for Spring 7 and above).| |null| -|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a pagination-metadata property) and replace their generated references with org.springframework.data.web.PagedModel<T>. The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| +|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T> generated into config package (default 'org.openapitools.configuration'). The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|server title name or client service name| |OpenAPI Spring| |unhandledException|Declare operation methods to throw a generic exception and allow unhandled exceptions (useful for Spring `@ControllerAdvice` directives).| |false| diff --git a/docs/generators/kotlin-spring.md b/docs/generators/kotlin-spring.md index 39bcf6c6d463..f99ca6628407 100644 --- a/docs/generators/kotlin-spring.md +++ b/docs/generators/kotlin-spring.md @@ -58,7 +58,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |null| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |null| |sourceFolder|source folder for generated code| |src/main/kotlin| -|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a pagination-metadata property) and replace their generated references with org.springframework.data.web.PagedModel<T>. The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| +|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T> generated into config package (default 'org.openapitools.configuration'). The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| |title|server title name or client service name| |OpenAPI Kotlin Spring| |useBeanValidation|Use BeanValidation API annotations to validate data types| |true| |useFeignClientUrl|Whether to generate Feign client with url parameter.| |true| diff --git a/docs/generators/spring.md b/docs/generators/spring.md index c674a42c6099..0df9b73b59a9 100644 --- a/docs/generators/spring.md +++ b/docs/generators/spring.md @@ -97,7 +97,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| |springApiVersion|Value for 'version' attribute in @RequestMapping (for Spring 7 and above).| |null| -|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a pagination-metadata property) and replace their generated references with org.springframework.data.web.PagedModel<T>. The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| +|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T> generated into config package (default 'org.openapitools.configuration'). The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|server title name or client service name| |OpenAPI Spring| |unhandledException|Declare operation methods to throw a generic exception and allow unhandled exceptions (useful for Spring `@ControllerAdvice` directives).| |false| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java index 2afa55b8aa9e..98e752d4775b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java @@ -298,9 +298,9 @@ public KotlinSpringServerCodegen() { addSwitch(GENERATE_SORT_VALIDATION, "Generate a @ValidSort annotation and SortValidator class, and apply @ValidSort to the injected Pageable parameter of operations whose 'sort' parameter has enum values. The annotation validates that sort values in the Pageable object match the allowed enum values from the spec. Requires useBeanValidation=true and library=spring-boot.", generateSortValidation); addSwitch(GENERATE_PAGEABLE_CONSTRAINT_VALIDATION, "Generate a @ValidPageable annotation and PageableConstraintValidator class, and apply @ValidPageable to the injected Pageable parameter of operations whose 'page' or 'size' parameter specifies a maximum constraint. The annotation enforces those constraints on the Pageable object that replaces the individual page/size query parameters. Requires useBeanValidation=true and library=spring-boot.", generatePageableConstraintValidation); addSwitch(SUBSTITUTE_GENERIC_PAGED_MODEL, - "Detect schemas that represent paginated responses (an object with a 'content' array property and a " + "Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' " + "pagination-metadata property) and replace their generated references with " - + "org.springframework.data.web.PagedModel. The detected page schemas and the pagination metadata " + + "PagedModel generated into config package (default 'org.openapitools.configuration'). The detected page schemas and the pagination metadata " + "schema are suppressed from code generation. Only applies when library=spring-boot.", substituteGenericPagedModel); addSwitch(COMPANION_OBJECT, "Whether to generate companion objects in data classes, enabling companion extensions.", companionObject); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java index 0eb0e9ed36dd..ac7022cb1632 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java @@ -376,9 +376,9 @@ public SpringCodegen() { + "Requires useBeanValidation=true and library=spring-boot.", generatePageableConstraintValidation)); cliOptions.add(CliOption.newBoolean(SUBSTITUTE_GENERIC_PAGED_MODEL, - "Detect schemas that represent paginated responses (an object with a 'content' array property and a " + "Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' " + "pagination-metadata property) and replace their generated references with " - + "org.springframework.data.web.PagedModel. The detected page schemas and the pagination metadata " + + "PagedModel generated into config package (default 'org.openapitools.configuration'). The detected page schemas and the pagination metadata " + "schema are suppressed from code generation. Only applies when library=spring-boot.", substituteGenericPagedModel)); From 7de158b6e7d845e8f6e05aa76ec8b7c2c7eab56a Mon Sep 17 00:00:00 2001 From: Jachym Metlicka Date: Tue, 21 Apr 2026 17:07:14 +0200 Subject: [PATCH 5/6] update documentation --- docs/generators/java-camel.md | 2 +- docs/generators/kotlin-spring.md | 2 +- docs/generators/spring.md | 2 +- .../codegen/languages/KotlinSpringServerCodegen.java | 2 +- .../java/org/openapitools/codegen/languages/SpringCodegen.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/generators/java-camel.md b/docs/generators/java-camel.md index 72b9f8e0a2ff..6ddd7bb96cad 100644 --- a/docs/generators/java-camel.md +++ b/docs/generators/java-camel.md @@ -104,7 +104,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| |springApiVersion|Value for 'version' attribute in @RequestMapping (for Spring 7 and above).| |null| -|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T> generated into config package (default 'org.openapitools.configuration'). The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| +|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T>. By default this uses a generated type in the config package (default 'org.openapitools.configuration'), but `importMappings.PagedModel` can override it to a custom/FQCN-mapped type. The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|server title name or client service name| |OpenAPI Spring| |unhandledException|Declare operation methods to throw a generic exception and allow unhandled exceptions (useful for Spring `@ControllerAdvice` directives).| |false| diff --git a/docs/generators/kotlin-spring.md b/docs/generators/kotlin-spring.md index f99ca6628407..9177ce41915c 100644 --- a/docs/generators/kotlin-spring.md +++ b/docs/generators/kotlin-spring.md @@ -58,7 +58,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |null| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |null| |sourceFolder|source folder for generated code| |src/main/kotlin| -|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T> generated into config package (default 'org.openapitools.configuration'). The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| +|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T>. By default this uses a generated type in the config package (default 'org.openapitools.configuration'), but `importMappings.PagedModel` can override it to a custom/FQCN-mapped type. The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| |title|server title name or client service name| |OpenAPI Kotlin Spring| |useBeanValidation|Use BeanValidation API annotations to validate data types| |true| |useFeignClientUrl|Whether to generate Feign client with url parameter.| |true| diff --git a/docs/generators/spring.md b/docs/generators/spring.md index 0df9b73b59a9..76bd12c9f43b 100644 --- a/docs/generators/spring.md +++ b/docs/generators/spring.md @@ -97,7 +97,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| |springApiVersion|Value for 'version' attribute in @RequestMapping (for Spring 7 and above).| |null| -|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T> generated into config package (default 'org.openapitools.configuration'). The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| +|substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T>. By default this uses a generated type in the config package (default 'org.openapitools.configuration'), but `importMappings.PagedModel` can override it to a custom/FQCN-mapped type. The detected page schemas and the pagination metadata schema are suppressed from code generation. Only applies when library=spring-boot.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|server title name or client service name| |OpenAPI Spring| |unhandledException|Declare operation methods to throw a generic exception and allow unhandled exceptions (useful for Spring `@ControllerAdvice` directives).| |false| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java index 98e752d4775b..da072abbbd5b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java @@ -300,7 +300,7 @@ public KotlinSpringServerCodegen() { addSwitch(SUBSTITUTE_GENERIC_PAGED_MODEL, "Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' " + "pagination-metadata property) and replace their generated references with " - + "PagedModel generated into config package (default 'org.openapitools.configuration'). The detected page schemas and the pagination metadata " + + "PagedModel. By default this uses a generated type in the config package (default 'org.openapitools.configuration'), but `importMappings.PagedModel` can override it to a custom/FQCN-mapped type. The detected page schemas and the pagination metadata " + "schema are suppressed from code generation. Only applies when library=spring-boot.", substituteGenericPagedModel); addSwitch(COMPANION_OBJECT, "Whether to generate companion objects in data classes, enabling companion extensions.", companionObject); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java index ac7022cb1632..86c81fbd4ce8 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java @@ -378,7 +378,7 @@ public SpringCodegen() { cliOptions.add(CliOption.newBoolean(SUBSTITUTE_GENERIC_PAGED_MODEL, "Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' " + "pagination-metadata property) and replace their generated references with " - + "PagedModel generated into config package (default 'org.openapitools.configuration'). The detected page schemas and the pagination metadata " + + "PagedModel. By default this uses a generated type in the config package (default 'org.openapitools.configuration'), but `importMappings.PagedModel` can override it to a custom/FQCN-mapped type. The detected page schemas and the pagination metadata " + "schema are suppressed from code generation. Only applies when library=spring-boot.", substituteGenericPagedModel)); From 93bc67a5c4f7eca9fc34e60522cb284764d34a44 Mon Sep 17 00:00:00 2001 From: Jachym Metlicka Date: Tue, 21 Apr 2026 17:34:50 +0200 Subject: [PATCH 6/6] implement feedback from CR --- .../codegen/languages/KotlinSpringServerCodegen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java index da072abbbd5b..9c5c8a798691 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java @@ -1221,7 +1221,7 @@ public void preprocessOpenAPI(OpenAPI openAPI) { String fqn = importMapping.get("PagedModel"); pagedModelClassName = fqn.substring(fqn.lastIndexOf('.') + 1); if (!pagedModelClassName.equals("PagedModel")) { - importMapping.put(pagedModelClassName, fqn); + importMapping.putIfAbsent(pagedModelClassName, fqn); } LOGGER.info("substituteGenericPagedModel: detected {} paged-model schema(s): {}", pagedModelRegistry.size(), pagedModelRegistry.keySet());