diff --git a/.github/workflows/samples-kotlin-server-jdk17.yaml b/.github/workflows/samples-kotlin-server-jdk17.yaml
index e5dc4d20ade..f79503de54f 100644
--- a/.github/workflows/samples-kotlin-server-jdk17.yaml
+++ b/.github/workflows/samples-kotlin-server-jdk17.yaml
@@ -25,6 +25,7 @@ jobs:
sample:
# server
- samples/server/petstore/kotlin-springboot-3
+ - samples/server/petstore/kotlin-springboot-request
# comment out due to gradle build failure
# - samples/server/petstore/kotlin-spring-default/
steps:
diff --git a/bin/configs/kotlin-spring-boot-request.yaml b/bin/configs/kotlin-spring-boot-request.yaml
new file mode 100644
index 00000000000..45cd1f00334
--- /dev/null
+++ b/bin/configs/kotlin-spring-boot-request.yaml
@@ -0,0 +1,9 @@
+generatorName: kotlin-spring
+outputDir: samples/server/petstore/kotlin-springboot-request
+library: spring-boot
+inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/kotlin-spring
+additionalProperties:
+ appendRequestToHandler: true
+ interfaceOnly: true
+ useSpringBoot3: true
diff --git a/docs/generators/kotlin-spring.md b/docs/generators/kotlin-spring.md
index 53cc95a29fa..f466d7ced80 100644
--- a/docs/generators/kotlin-spring.md
+++ b/docs/generators/kotlin-spring.md
@@ -22,6 +22,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|annotationLibrary|Select the complementary documentation annotation library.|
- **none**
- Do not annotate Model and Api with complementary annotations.
- **swagger1**
- Annotate Model and Api using the Swagger Annotations 1.x library.
- **swagger2**
- Annotate Model and Api using the Swagger Annotations 2.x library.
|swagger2|
|apiPackage|api package for generated code| |org.openapitools.api|
|apiSuffix|suffix for api classes| |Api|
+|appendRequestToHandler|Append ServerHttpRequest to handler method for getting request stuff| |false|
|artifactId|Generated artifact id (name of jar).| |openapi-spring|
|artifactVersion|Generated artifact's package version.| |1.0.0|
|basePackage|base package (invokerPackage) for generated code| |org.openapitools|
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 14526f553ce..ce14fe19a63 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
@@ -101,6 +101,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
public static final String BEAN_QUALIFIERS = "beanQualifiers";
public static final String USE_SPRING_BOOT3 = "useSpringBoot3";
+ public static final String APPEND_REQUEST_TO_HANDLER = "appendRequestToHandler";
private String basePackage;
protected String configPackage;
@@ -203,6 +204,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
"@RestController annotations. May be used to prevent bean names clash if multiple generated libraries" +
" (contexts) added to single project.", beanQualifiers);
addSwitch(USE_SPRING_BOOT3, "Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.", useSpringBoot3);
+ addSwitch(APPEND_REQUEST_TO_HANDLER, "Append ServerHttpRequest to handler method for getting request stuff", false);
supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
supportedLibraries.put(SPRING_CLOUD_LIBRARY,
"Spring-Cloud-Feign client with Spring-Boot auto-configured settings.");
@@ -377,6 +379,10 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
this.useTags = useTags;
}
+ public boolean isAppendRequestToHandler() {
+ return Boolean.parseBoolean(additionalProperties.get(APPEND_REQUEST_TO_HANDLER).toString());
+ }
+
public void setUseSpringBoot3(boolean isSpringBoot3) {
this.useSpringBoot3 = isSpringBoot3;
}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache
index 31790185444..8672c263cf5 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache
@@ -29,6 +29,9 @@ import org.springframework.validation.annotation.Validated
import org.springframework.web.context.request.NativeWebRequest
import org.springframework.beans.factory.annotation.Autowired
+{{#appendRequestToHandler}}
+import org.springframework.http.server.reactive.ServerHttpRequest
+{{/appendRequestToHandler}}
{{#useBeanValidation}}
import {{javaxPackage}}.validation.Valid
import {{javaxPackage}}.validation.constraints.DecimalMax
@@ -87,7 +90,7 @@ class {{classname}}Controller({{#serviceInterface}}@Autowired(required = true) v
produces = [{{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}]{{/hasProduces}}{{#hasConsumes}},
consumes = [{{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}}]{{/hasConsumes}}{{/singleContentTypes}}
)
- {{#reactive}}{{^isArray}}suspend {{/isArray}}{{/reactive}}fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}},{{/-last}}{{/allParams}}): ResponseEntity<{{>returnTypes}}> {
+ {{#reactive}}{{^isArray}}suspend {{/isArray}}{{/reactive}}fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}},{{/-last}}{{/allParams}}{{#appendRequestToHandler}}, serverHttpRequest: ServerHttpRequest{{/appendRequestToHandler}}): ResponseEntity<{{>returnTypes}}> {
return {{>returnValue}}
}
{{/operation}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache
index f403cfb2820..6a8fd486625 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache
@@ -26,6 +26,9 @@ import io.swagger.annotations.AuthorizationScope
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
+{{#appendRequestToHandler}}
+import org.springframework.http.server.reactive.ServerHttpRequest
+{{/appendRequestToHandler}}
import org.springframework.web.bind.annotation.*
{{#useBeanValidation}}
@@ -98,7 +101,7 @@ interface {{classname}} {
produces = [{{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}]{{/hasProduces}}{{#hasConsumes}},
consumes = [{{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}}]{{/hasConsumes}}{{/singleContentTypes}}
)
- {{#reactive}}{{^isArray}}suspend {{/isArray}}{{/reactive}}fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}},{{/-last}}{{/allParams}}): ResponseEntity<{{>returnTypes}}>{{^skipDefaultInterface}} {
+ {{#reactive}}{{^isArray}}suspend {{/isArray}}{{/reactive}}fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}},{{/-last}}{{/allParams}}{{#appendRequestToHandler}}, serverHttpRequest: ServerHttpRequest{{/appendRequestToHandler}}): ResponseEntity<{{>returnTypes}}>{{^skipDefaultInterface}} {
{{^isDelegate}}
return {{>returnValue}}
{{/isDelegate}}
diff --git a/samples/server/petstore/kotlin-springboot-request/.openapi-generator-ignore b/samples/server/petstore/kotlin-springboot-request/.openapi-generator-ignore
new file mode 100644
index 00000000000..7484ee590a3
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
diff --git a/samples/server/petstore/kotlin-springboot-request/.openapi-generator/FILES b/samples/server/petstore/kotlin-springboot-request/.openapi-generator/FILES
new file mode 100644
index 00000000000..843a3288acd
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/.openapi-generator/FILES
@@ -0,0 +1,17 @@
+.openapi-generator-ignore
+README.md
+build.gradle.kts
+pom.xml
+settings.gradle
+src/main/kotlin/org/openapitools/SpringDocConfiguration.kt
+src/main/kotlin/org/openapitools/api/ApiUtil.kt
+src/main/kotlin/org/openapitools/api/Exceptions.kt
+src/main/kotlin/org/openapitools/api/PetApi.kt
+src/main/kotlin/org/openapitools/api/StoreApi.kt
+src/main/kotlin/org/openapitools/api/UserApi.kt
+src/main/kotlin/org/openapitools/model/Category.kt
+src/main/kotlin/org/openapitools/model/ModelApiResponse.kt
+src/main/kotlin/org/openapitools/model/Order.kt
+src/main/kotlin/org/openapitools/model/Pet.kt
+src/main/kotlin/org/openapitools/model/Tag.kt
+src/main/kotlin/org/openapitools/model/User.kt
diff --git a/samples/server/petstore/kotlin-springboot-request/.openapi-generator/VERSION b/samples/server/petstore/kotlin-springboot-request/.openapi-generator/VERSION
new file mode 100644
index 00000000000..0f78c31cdc7
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.2.0-SNAPSHOT
\ No newline at end of file
diff --git a/samples/server/petstore/kotlin-springboot-request/README.md b/samples/server/petstore/kotlin-springboot-request/README.md
new file mode 100644
index 00000000000..b6865a08113
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/README.md
@@ -0,0 +1,21 @@
+# openAPIPetstore
+
+This Kotlin based [Spring Boot](https://spring.io/projects/spring-boot) application has been generated using the [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator).
+
+## Getting Started
+
+This document assumes you have either maven or gradle available, either via the wrapper or otherwise. This does not come with a gradle / maven wrapper checked in.
+
+By default a [`pom.xml`](pom.xml) file will be generated. If you specified `gradleBuildFile=true` when generating this project, a `build.gradle.kts` will also be generated. Note this uses [Gradle Kotlin DSL](https://github.com/gradle/kotlin-dsl).
+
+To build the project using maven, run:
+```bash
+mvn package && java -jar target/openapi-spring-1.0.0.jar
+```
+
+To build the project using gradle, run:
+```bash
+gradle build && java -jar build/libs/openapi-spring-1.0.0.jar
+```
+
+If all builds successfully, the server should run on [http://localhost:8080/](http://localhost:8080/)
diff --git a/samples/server/petstore/kotlin-springboot-request/build.gradle.kts b/samples/server/petstore/kotlin-springboot-request/build.gradle.kts
new file mode 100644
index 00000000000..f8ef1123955
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/build.gradle.kts
@@ -0,0 +1,43 @@
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+group = "org.openapitools"
+version = "1.0.0"
+java.sourceCompatibility = JavaVersion.VERSION_17
+
+repositories {
+ mavenCentral()
+ maven { url = uri("https://repo.spring.io/milestone") }
+}
+
+tasks.withType {
+ kotlinOptions.jvmTarget = "17"
+}
+
+plugins {
+ val kotlinVersion = "1.7.10"
+ id("org.jetbrains.kotlin.jvm") version kotlinVersion
+ id("org.jetbrains.kotlin.plugin.jpa") version kotlinVersion
+ id("org.jetbrains.kotlin.plugin.spring") version kotlinVersion
+ id("org.springframework.boot") version "3.0.2"
+ id("io.spring.dependency-management") version "1.0.14.RELEASE"
+}
+
+dependencies {
+ implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
+ implementation("org.jetbrains.kotlin:kotlin-reflect")
+ implementation("org.springframework.boot:spring-boot-starter-web")
+ implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.0-M5")
+
+ implementation("com.google.code.findbugs:jsr305:3.0.2")
+ implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml")
+ implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml")
+ implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
+ implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
+ implementation("jakarta.validation:jakarta.validation-api")
+ implementation("jakarta.annotation:jakarta.annotation-api:2.1.0")
+
+ testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
+ testImplementation("org.springframework.boot:spring-boot-starter-test") {
+ exclude(module = "junit")
+ }
+}
diff --git a/samples/server/petstore/kotlin-springboot-request/pom.xml b/samples/server/petstore/kotlin-springboot-request/pom.xml
new file mode 100644
index 00000000000..d3dd81b25a8
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/pom.xml
@@ -0,0 +1,138 @@
+
+ 4.0.0
+ org.openapitools
+ openapi-spring
+ jar
+ openapi-spring
+ 1.0.0
+
+ 2.2.0
+ 3.0.2
+ 2.1.0
+ 1.7.10
+
+ 1.7.10
+ UTF-8
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.1.3
+
+
+
+ repository.spring.milestone
+ Spring Milestone Repository
+ https://repo.spring.io/milestone
+
+
+
+
+ spring-milestones
+ https://repo.spring.io/milestone
+
+
+
+ ${project.basedir}/src/main/kotlin
+ ${project.basedir}/src/test/kotlin
+
+
+ kotlin-maven-plugin
+ org.jetbrains.kotlin
+ ${kotlin.version}
+
+
+ spring
+
+ 17
+
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-allopen
+ ${kotlin.version}
+
+
+
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ ${kotlin.version}
+
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+ ${kotlin.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ ${springdoc-openapi.version}
+
+
+
+
+ com.google.code.findbugs
+ jsr305
+ ${findbugs-jsr305.version}
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+ com.fasterxml.jackson.module
+ jackson-module-kotlin
+
+
+
+ jakarta.validation
+ jakarta.validation-api
+
+
+ jakarta.annotation
+ jakarta.annotation-api
+ ${jakarta-annotation.version}
+ provided
+
+
+ org.jetbrains.kotlin
+ kotlin-test-junit5
+ ${kotlin-test-junit5.version}
+ test
+
+
+
diff --git a/samples/server/petstore/kotlin-springboot-request/settings.gradle b/samples/server/petstore/kotlin-springboot-request/settings.gradle
new file mode 100644
index 00000000000..14844905cd4
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/settings.gradle
@@ -0,0 +1,15 @@
+pluginManagement {
+ repositories {
+ maven { url = uri("https://repo.spring.io/snapshot") }
+ maven { url = uri("https://repo.spring.io/milestone") }
+ gradlePluginPortal()
+ }
+ resolutionStrategy {
+ eachPlugin {
+ if (requested.id.id == "org.springframework.boot") {
+ useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}")
+ }
+ }
+ }
+}
+rootProject.name = "openapi-spring"
diff --git a/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/SpringDocConfiguration.kt b/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/SpringDocConfiguration.kt
new file mode 100644
index 00000000000..ab4d5eb17b8
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/SpringDocConfiguration.kt
@@ -0,0 +1,42 @@
+package org.openapitools
+
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+
+import io.swagger.v3.oas.models.OpenAPI
+import io.swagger.v3.oas.models.info.Info
+import io.swagger.v3.oas.models.info.Contact
+import io.swagger.v3.oas.models.info.License
+import io.swagger.v3.oas.models.Components
+import io.swagger.v3.oas.models.security.SecurityScheme
+
+@Configuration
+class SpringDocConfiguration {
+
+ @Bean
+ fun apiInfo(): OpenAPI {
+ return OpenAPI()
+ .info(
+ Info()
+ .title("OpenAPI Petstore")
+ .description("This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.")
+ .license(
+ License()
+ .name("Apache-2.0")
+ .url("https://www.apache.org/licenses/LICENSE-2.0.html")
+ )
+ .version("1.0.0")
+ )
+ .components(
+ Components()
+ .addSecuritySchemes("petstore_auth", SecurityScheme()
+ .type(SecurityScheme.Type.OAUTH2)
+ )
+ .addSecuritySchemes("api_key", SecurityScheme()
+ .type(SecurityScheme.Type.APIKEY)
+ .`in`(SecurityScheme.In.HEADER)
+ .name("api_key")
+ )
+ )
+ }
+}
diff --git a/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/ApiUtil.kt b/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/ApiUtil.kt
new file mode 100644
index 00000000000..03344e13b47
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/ApiUtil.kt
@@ -0,0 +1,19 @@
+package org.openapitools.api
+
+import org.springframework.web.context.request.NativeWebRequest
+
+import jakarta.servlet.http.HttpServletResponse
+import java.io.IOException
+
+object ApiUtil {
+ fun setExampleResponse(req: NativeWebRequest, contentType: String, example: String) {
+ try {
+ val res = req.getNativeResponse(HttpServletResponse::class.java)
+ res?.characterEncoding = "UTF-8"
+ res?.addHeader("Content-Type", contentType)
+ res?.writer?.print(example)
+ } catch (e: IOException) {
+ throw RuntimeException(e)
+ }
+ }
+}
diff --git a/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/Exceptions.kt b/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/Exceptions.kt
new file mode 100644
index 00000000000..117161bf65b
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/Exceptions.kt
@@ -0,0 +1,29 @@
+package org.openapitools.api
+
+import org.springframework.http.HttpStatus
+import org.springframework.web.bind.annotation.ControllerAdvice
+import org.springframework.web.bind.annotation.ExceptionHandler
+import jakarta.servlet.http.HttpServletResponse
+import jakarta.validation.ConstraintViolationException
+
+// TODO Extend ApiException for custom exception handling, e.g. the below NotFound exception
+sealed class ApiException(msg: String, val code: Int) : Exception(msg)
+
+class NotFoundException(msg: String, code: Int = HttpStatus.NOT_FOUND.value()) : ApiException(msg, code)
+
+
+@ControllerAdvice
+class DefaultExceptionHandler {
+
+ @ExceptionHandler(value = [ApiException::class])
+ fun onApiException(ex: ApiException, response: HttpServletResponse): Unit =
+ response.sendError(ex.code, ex.message)
+
+ @ExceptionHandler(value = [NotImplementedError::class])
+ fun onNotImplemented(ex: NotImplementedError, response: HttpServletResponse): Unit =
+ response.sendError(HttpStatus.NOT_IMPLEMENTED.value())
+
+ @ExceptionHandler(value = [ConstraintViolationException::class])
+ fun onConstraintViolation(ex: ConstraintViolationException, response: HttpServletResponse): Unit =
+ response.sendError(HttpStatus.BAD_REQUEST.value(), ex.constraintViolations.joinToString(", ") { it.message })
+}
diff --git a/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/PetApi.kt b/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/PetApi.kt
new file mode 100644
index 00000000000..f5372c85977
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/PetApi.kt
@@ -0,0 +1,191 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.2.0-SNAPSHOT).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+*/
+package org.openapitools.api
+
+import org.openapitools.model.ModelApiResponse
+import org.openapitools.model.Pet
+import io.swagger.v3.oas.annotations.*
+import io.swagger.v3.oas.annotations.enums.*
+import io.swagger.v3.oas.annotations.media.*
+import io.swagger.v3.oas.annotations.responses.*
+import io.swagger.v3.oas.annotations.security.*
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.springframework.http.ResponseEntity
+import org.springframework.http.server.reactive.ServerHttpRequest
+
+import org.springframework.web.bind.annotation.*
+import org.springframework.validation.annotation.Validated
+import org.springframework.web.context.request.NativeWebRequest
+import org.springframework.beans.factory.annotation.Autowired
+
+import jakarta.validation.constraints.DecimalMax
+import jakarta.validation.constraints.DecimalMin
+import jakarta.validation.constraints.Email
+import jakarta.validation.constraints.Max
+import jakarta.validation.constraints.Min
+import jakarta.validation.constraints.NotNull
+import jakarta.validation.constraints.Pattern
+import jakarta.validation.constraints.Size
+import jakarta.validation.Valid
+
+import kotlin.collections.List
+import kotlin.collections.Map
+
+@Validated
+@RequestMapping("\${api.base-path:/v2}")
+interface PetApi {
+
+ @Operation(
+ summary = "Add a new pet to the store",
+ operationId = "addPet",
+ description = """""",
+ responses = [
+ ApiResponse(responseCode = "405", description = "Invalid input")
+ ],
+ security = [ SecurityRequirement(name = "petstore_auth", scopes = [ "write:pets", "read:pets" ]) ]
+ )
+ @RequestMapping(
+ method = [RequestMethod.POST],
+ value = ["/pet"],
+ consumes = ["application/json", "application/xml"]
+ )
+ fun addPet(@Parameter(description = "Pet object that needs to be added to the store", required = true) @Valid @RequestBody body: Pet, serverHttpRequest: ServerHttpRequest): ResponseEntity {
+ return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
+ }
+
+ @Operation(
+ summary = "Deletes a pet",
+ operationId = "deletePet",
+ description = """""",
+ responses = [
+ ApiResponse(responseCode = "400", description = "Invalid pet value")
+ ],
+ security = [ SecurityRequirement(name = "petstore_auth", scopes = [ "write:pets", "read:pets" ]) ]
+ )
+ @RequestMapping(
+ method = [RequestMethod.DELETE],
+ value = ["/pet/{petId}"]
+ )
+ fun deletePet(@Parameter(description = "Pet id to delete", required = true) @PathVariable("petId") petId: kotlin.Long,@Parameter(description = "", `in` = ParameterIn.HEADER) @RequestHeader(value = "api_key", required = false) apiKey: kotlin.String?, serverHttpRequest: ServerHttpRequest): ResponseEntity {
+ return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
+ }
+
+ @Operation(
+ summary = "Finds Pets by status",
+ operationId = "findPetsByStatus",
+ description = """Multiple status values can be provided with comma separated strings""",
+ responses = [
+ ApiResponse(responseCode = "200", description = "successful operation", content = [Content(array = ArraySchema(schema = Schema(implementation = Pet::class)))]),
+ ApiResponse(responseCode = "400", description = "Invalid status value")
+ ],
+ security = [ SecurityRequirement(name = "petstore_auth", scopes = [ "write:pets", "read:pets" ]) ]
+ )
+ @RequestMapping(
+ method = [RequestMethod.GET],
+ value = ["/pet/findByStatus"],
+ produces = ["application/xml", "application/json"]
+ )
+ fun findPetsByStatus(@NotNull @Parameter(description = "Status values that need to be considered for filter", required = true, schema = Schema(allowableValues = ["available", "pending", "sold"])) @Valid @RequestParam(value = "status", required = true) status: kotlin.collections.List, serverHttpRequest: ServerHttpRequest): ResponseEntity> {
+ return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
+ }
+
+ @Operation(
+ summary = "Finds Pets by tags",
+ operationId = "findPetsByTags",
+ description = """Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.""",
+ responses = [
+ ApiResponse(responseCode = "200", description = "successful operation", content = [Content(array = ArraySchema(schema = Schema(implementation = Pet::class)))]),
+ ApiResponse(responseCode = "400", description = "Invalid tag value")
+ ],
+ security = [ SecurityRequirement(name = "petstore_auth", scopes = [ "write:pets", "read:pets" ]) ]
+ )
+ @RequestMapping(
+ method = [RequestMethod.GET],
+ value = ["/pet/findByTags"],
+ produces = ["application/xml", "application/json"]
+ )
+ fun findPetsByTags(@NotNull @Parameter(description = "Tags to filter by", required = true) @Valid @RequestParam(value = "tags", required = true) tags: kotlin.collections.List, serverHttpRequest: ServerHttpRequest): ResponseEntity> {
+ return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
+ }
+
+ @Operation(
+ summary = "Find pet by ID",
+ operationId = "getPetById",
+ description = """Returns a single pet""",
+ responses = [
+ ApiResponse(responseCode = "200", description = "successful operation", content = [Content(schema = Schema(implementation = Pet::class))]),
+ ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+ ApiResponse(responseCode = "404", description = "Pet not found")
+ ],
+ security = [ SecurityRequirement(name = "api_key") ]
+ )
+ @RequestMapping(
+ method = [RequestMethod.GET],
+ value = ["/pet/{petId}"],
+ produces = ["application/xml", "application/json"]
+ )
+ fun getPetById(@Parameter(description = "ID of pet to return", required = true) @PathVariable("petId") petId: kotlin.Long, serverHttpRequest: ServerHttpRequest): ResponseEntity {
+ return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
+ }
+
+ @Operation(
+ summary = "Update an existing pet",
+ operationId = "updatePet",
+ description = """""",
+ responses = [
+ ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+ ApiResponse(responseCode = "404", description = "Pet not found"),
+ ApiResponse(responseCode = "405", description = "Validation exception")
+ ],
+ security = [ SecurityRequirement(name = "petstore_auth", scopes = [ "write:pets", "read:pets" ]) ]
+ )
+ @RequestMapping(
+ method = [RequestMethod.PUT],
+ value = ["/pet"],
+ consumes = ["application/json", "application/xml"]
+ )
+ fun updatePet(@Parameter(description = "Pet object that needs to be added to the store", required = true) @Valid @RequestBody body: Pet, serverHttpRequest: ServerHttpRequest): ResponseEntity {
+ return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
+ }
+
+ @Operation(
+ summary = "Updates a pet in the store with form data",
+ operationId = "updatePetWithForm",
+ description = """""",
+ responses = [
+ ApiResponse(responseCode = "405", description = "Invalid input")
+ ],
+ security = [ SecurityRequirement(name = "petstore_auth", scopes = [ "write:pets", "read:pets" ]) ]
+ )
+ @RequestMapping(
+ method = [RequestMethod.POST],
+ value = ["/pet/{petId}"],
+ consumes = ["application/x-www-form-urlencoded"]
+ )
+ fun updatePetWithForm(@Parameter(description = "ID of pet that needs to be updated", required = true) @PathVariable("petId") petId: kotlin.Long,@Parameter(description = "Updated name of the pet") @RequestParam(value = "name", required = false) name: kotlin.String? ,@Parameter(description = "Updated status of the pet") @RequestParam(value = "status", required = false) status: kotlin.String? , serverHttpRequest: ServerHttpRequest): ResponseEntity {
+ return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
+ }
+
+ @Operation(
+ summary = "uploads an image",
+ operationId = "uploadFile",
+ description = """""",
+ responses = [
+ ApiResponse(responseCode = "200", description = "successful operation", content = [Content(schema = Schema(implementation = ModelApiResponse::class))])
+ ],
+ security = [ SecurityRequirement(name = "petstore_auth", scopes = [ "write:pets", "read:pets" ]) ]
+ )
+ @RequestMapping(
+ method = [RequestMethod.POST],
+ value = ["/pet/{petId}/uploadImage"],
+ produces = ["application/json"],
+ consumes = ["multipart/form-data"]
+ )
+ fun uploadFile(@Parameter(description = "ID of pet to update", required = true) @PathVariable("petId") petId: kotlin.Long,@Parameter(description = "Additional data to pass to server") @RequestParam(value = "additionalMetadata", required = false) additionalMetadata: kotlin.String? ,@Parameter(description = "file detail") @Valid @RequestPart("file") file: org.springframework.core.io.Resource?, serverHttpRequest: ServerHttpRequest): ResponseEntity {
+ return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
+ }
+}
diff --git a/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/StoreApi.kt b/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/StoreApi.kt
new file mode 100644
index 00000000000..7f84f6d301e
--- /dev/null
+++ b/samples/server/petstore/kotlin-springboot-request/src/main/kotlin/org/openapitools/api/StoreApi.kt
@@ -0,0 +1,112 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.2.0-SNAPSHOT).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+*/
+package org.openapitools.api
+
+import org.openapitools.model.Order
+import io.swagger.v3.oas.annotations.*
+import io.swagger.v3.oas.annotations.enums.*
+import io.swagger.v3.oas.annotations.media.*
+import io.swagger.v3.oas.annotations.responses.*
+import io.swagger.v3.oas.annotations.security.*
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.springframework.http.ResponseEntity
+import org.springframework.http.server.reactive.ServerHttpRequest
+
+import org.springframework.web.bind.annotation.*
+import org.springframework.validation.annotation.Validated
+import org.springframework.web.context.request.NativeWebRequest
+import org.springframework.beans.factory.annotation.Autowired
+
+import jakarta.validation.constraints.DecimalMax
+import jakarta.validation.constraints.DecimalMin
+import jakarta.validation.constraints.Email
+import jakarta.validation.constraints.Max
+import jakarta.validation.constraints.Min
+import jakarta.validation.constraints.NotNull
+import jakarta.validation.constraints.Pattern
+import jakarta.validation.constraints.Size
+import jakarta.validation.Valid
+
+import kotlin.collections.List
+import kotlin.collections.Map
+
+@Validated
+@RequestMapping("\${api.base-path:/v2}")
+interface StoreApi {
+
+ @Operation(
+ summary = "Delete purchase order by ID",
+ operationId = "deleteOrder",
+ description = """For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors""",
+ responses = [
+ ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+ ApiResponse(responseCode = "404", description = "Order not found")
+ ]
+ )
+ @RequestMapping(
+ method = [RequestMethod.DELETE],
+ value = ["/store/order/{orderId}"]
+ )
+ fun deleteOrder(@Parameter(description = "ID of the order that needs to be deleted", required = true) @PathVariable("orderId") orderId: kotlin.String, serverHttpRequest: ServerHttpRequest): ResponseEntity {
+ return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
+ }
+
+ @Operation(
+ summary = "Returns pet inventories by status",
+ operationId = "getInventory",
+ description = """Returns a map of status codes to quantities""",
+ responses = [
+ ApiResponse(responseCode = "200", description = "successful operation", content = [Content(schema = Schema(implementation = kotlin.collections.Map::class))])
+ ],
+ security = [ SecurityRequirement(name = "api_key") ]
+ )
+ @RequestMapping(
+ method = [RequestMethod.GET],
+ value = ["/store/inventory"],
+ produces = ["application/json"]
+ )
+ fun getInventory(, serverHttpRequest: ServerHttpRequest): ResponseEntity