From e249b6b2adad4d36b6d12639357f90d80511417f Mon Sep 17 00:00:00 2001 From: David Gracza Date: Sat, 25 Mar 2023 18:59:13 +0100 Subject: [PATCH] [Kotlin-Spring] add Kotlin based Spring-cloud openfeign generator --- .github/workflows/samples-kotlin-client.yaml | 1 + bin/configs/kotlin-spring-cloud.yaml | 12 + docs/generators/kotlin-spring.md | 4 +- .../languages/KotlinSpringServerCodegen.java | 124 ++++++++-- .../libraries/spring-cloud/README.mustache | 83 +++++++ .../libraries/spring-cloud/apiClient.mustache | 11 + .../apiKeyRequestInterceptor.mustache | 19 ++ .../spring-cloud/buildGradle-sb3-Kts.mustache | 68 +++++ .../spring-cloud/buildGradleKts.mustache | 75 ++++++ .../spring-cloud/clientConfiguration.mustache | 132 ++++++++++ .../libraries/spring-cloud/pom-sb3.mustache | 233 ++++++++++++++++++ .../libraries/spring-cloud/pom.mustache | 210 ++++++++++++++++ .../spring-cloud/settingsGradle.mustache | 15 ++ .../.openapi-generator-ignore | 23 ++ .../.openapi-generator/FILES | 18 ++ .../.openapi-generator/VERSION | 1 + .../petstore/kotlin-spring-cloud/README.md | 26 ++ .../kotlin-spring-cloud/build.gradle.kts | 63 +++++ .../petstore/kotlin-spring-cloud/pom.xml | 138 +++++++++++ .../kotlin-spring-cloud/settings.gradle | 15 ++ .../kotlin/org/openapitools/api/PetApi.kt | 117 +++++++++ .../org/openapitools/api/PetApiClient.kt | 11 + .../kotlin/org/openapitools/api/StoreApi.kt | 74 ++++++ .../org/openapitools/api/StoreApiClient.kt | 11 + .../kotlin/org/openapitools/api/UserApi.kt | 112 +++++++++ .../org/openapitools/api/UserApiClient.kt | 11 + .../configuration/ApiKeyRequestInterceptor.kt | 19 ++ .../configuration/ClientConfiguration.kt | 48 ++++ .../kotlin/org/openapitools/model/Category.kt | 29 +++ .../openapitools/model/ModelApiResponse.kt | 31 +++ .../kotlin/org/openapitools/model/Order.kt | 52 ++++ .../main/kotlin/org/openapitools/model/Pet.kt | 57 +++++ .../main/kotlin/org/openapitools/model/Tag.kt | 28 +++ .../kotlin/org/openapitools/model/User.kt | 46 ++++ 34 files changed, 1902 insertions(+), 15 deletions(-) create mode 100644 bin/configs/kotlin-spring-cloud.yaml create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/README.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/apiClient.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/apiKeyRequestInterceptor.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/buildGradle-sb3-Kts.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/buildGradleKts.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/clientConfiguration.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/pom-sb3.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/pom.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/settingsGradle.mustache create mode 100644 samples/client/petstore/kotlin-spring-cloud/.openapi-generator-ignore create mode 100644 samples/client/petstore/kotlin-spring-cloud/.openapi-generator/FILES create mode 100644 samples/client/petstore/kotlin-spring-cloud/.openapi-generator/VERSION create mode 100644 samples/client/petstore/kotlin-spring-cloud/README.md create mode 100644 samples/client/petstore/kotlin-spring-cloud/build.gradle.kts create mode 100644 samples/client/petstore/kotlin-spring-cloud/pom.xml create mode 100644 samples/client/petstore/kotlin-spring-cloud/settings.gradle create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/PetApi.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/PetApiClient.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/StoreApi.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/StoreApiClient.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/UserApi.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/UserApiClient.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/configuration/ApiKeyRequestInterceptor.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/configuration/ClientConfiguration.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Category.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/ModelApiResponse.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Order.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Pet.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Tag.kt create mode 100644 samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/User.kt diff --git a/.github/workflows/samples-kotlin-client.yaml b/.github/workflows/samples-kotlin-client.yaml index 653119c41300..d0ead8cbc205 100644 --- a/.github/workflows/samples-kotlin-client.yaml +++ b/.github/workflows/samples-kotlin-client.yaml @@ -56,6 +56,7 @@ jobs: - samples/client/petstore/kotlin-jvm-vertx-jackson - samples/client/petstore/kotlin-jvm-vertx-jackson-coroutines - samples/client/petstore/kotlin-jvm-vertx-moshi + - samples/client/petstore/kotlin-spring-cloud steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 diff --git a/bin/configs/kotlin-spring-cloud.yaml b/bin/configs/kotlin-spring-cloud.yaml new file mode 100644 index 000000000000..10e6f95a8057 --- /dev/null +++ b/bin/configs/kotlin-spring-cloud.yaml @@ -0,0 +1,12 @@ +generatorName: kotlin-spring +outputDir: samples/client/petstore/kotlin-spring-cloud +library: spring-cloud +inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml +templateDir: modules/openapi-generator/src/main/resources/kotlin-spring +additionalProperties: + documentationProvider: none + annotationLibrary: none + useSwaggerUI: "false" + serializableModel: "true" + beanValidations: "true" + interfaceOnly: "true" diff --git a/docs/generators/kotlin-spring.md b/docs/generators/kotlin-spring.md index 0bf820d705dc..24c83a9bf70d 100644 --- a/docs/generators/kotlin-spring.md +++ b/docs/generators/kotlin-spring.md @@ -26,6 +26,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |artifactVersion|Generated artifact's package version.| |1.0.0| |basePackage|base package (invokerPackage) for generated code| |org.openapitools| |beanQualifiers|Whether to add fully-qualifier class names as bean qualifiers in @Component and @RestController annotations. May be used to prevent bean names clash if multiple generated libraries (contexts) added to single project.| |false| +|configPackage|configuration package for generated code| |org.openapitools.configuration| |delegatePattern|Whether to generate the server files using the delegate pattern| |false| |documentationProvider|Select the OpenAPI documentation provider.|
**none**
Do not publish an OpenAPI specification.
**source**
Publish the original input OpenAPI specification.
**springfox**
Generate an OpenAPI 2 (fka Swagger RESTful API Documentation Specification) specification using SpringFox 2.x. Deprecated (for removal); use springdoc instead.
**springdoc**
Generate an OpenAPI 3 specification using SpringDoc.
|springdoc| |enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase| @@ -33,7 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |gradleBuildFile|generate a gradle build file using the Kotlin DSL| |true| |groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| |interfaceOnly|Whether to generate only API interface stubs without the server files.| |false| -|library|library template (sub-template)|
**spring-boot**
Spring-boot Server application.
|spring-boot| +|library|library template (sub-template)|
**spring-boot**
Spring-boot Server application.
**spring-cloud**
Spring-Cloud-Feign client with Spring-Boot auto-configured settings.
|spring-boot| |modelMutable|Create mutable models| |false| |modelPackage|model package for generated code| |org.openapitools.model| |packageName|Generated artifact package name.| |org.openapitools| @@ -50,6 +51,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sourceFolder|source folder for generated code| |src/main/kotlin| |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| |useSpringBoot3|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`.| |false| |useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true| |useTags|Whether to use tags for creating interface and controller class names| |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 2be4589572a8..540cef172372 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 @@ -22,11 +22,24 @@ import com.samskivert.mustache.Template; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; -import org.openapitools.codegen.*; +import org.openapitools.codegen.CliOption; +import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenParameter; +import org.openapitools.codegen.CodegenProperty; +import org.openapitools.codegen.CodegenResponse; +import org.openapitools.codegen.CodegenType; +import org.openapitools.codegen.SupportingFile; import org.openapitools.codegen.languages.features.BeanValidationFeatures; import org.openapitools.codegen.languages.features.DocumentationProviderFeatures; import org.openapitools.codegen.languages.features.SwaggerUIFeatures; -import org.openapitools.codegen.meta.features.*; +import org.openapitools.codegen.meta.features.DocumentationFeature; +import org.openapitools.codegen.meta.features.GlobalFeature; +import org.openapitools.codegen.meta.features.ParameterFeature; +import org.openapitools.codegen.meta.features.SchemaSupportFeature; +import org.openapitools.codegen.meta.features.SecurityFeature; +import org.openapitools.codegen.meta.features.WireFormatFeature; import org.openapitools.codegen.model.ModelMap; import org.openapitools.codegen.model.ModelsMap; import org.openapitools.codegen.model.OperationMap; @@ -39,7 +52,14 @@ import java.io.IOException; import java.io.Writer; import java.net.URL; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.regex.Matcher; import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER; @@ -58,10 +78,15 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen "ApiResponse" )); + public static final String OPEN_BRACE = "{"; + public static final String CLOSE_BRACE = "}"; + public static final String TITLE = "title"; public static final String SERVER_PORT = "serverPort"; + public static final String CONFIG_PACKAGE = "configPackage"; public static final String BASE_PACKAGE = "basePackage"; public static final String SPRING_BOOT = "spring-boot"; + public static final String SPRING_CLOUD_LIBRARY = "spring-cloud"; public static final String EXCEPTION_HANDLER = "exceptionHandler"; public static final String GRADLE_BUILD_FILE = "gradleBuildFile"; public static final String SERVICE_INTERFACE = "serviceInterface"; @@ -69,6 +94,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen public static final String SKIP_DEFAULT_INTERFACE = "skipDefaultInterface"; public static final String REACTIVE = "reactive"; public static final String INTERFACE_ONLY = "interfaceOnly"; + public static final String USE_FEIGN_CLIENT_URL = "useFeignClientUrl"; public static final String DELEGATE_PATTERN = "delegatePattern"; public static final String USE_TAGS = "useTags"; public static final String BEAN_QUALIFIERS = "beanQualifiers"; @@ -76,6 +102,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen public static final String USE_SPRING_BOOT3 = "useSpringBoot3"; private String basePackage; + protected String configPackage; private String invokerPackage; private String serverPort = "8080"; private String title = "OpenAPI Kotlin Spring"; @@ -88,6 +115,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen private boolean serviceImplementation = false; private boolean reactive = false; private boolean interfaceOnly = false; + protected boolean useFeignClientUrl = true; private boolean delegatePattern = false; protected boolean useTags = false; private boolean beanQualifiers = false; @@ -128,12 +156,16 @@ public KotlinSpringServerCodegen() { artifactId = "openapi-spring"; basePackage = invokerPackage = "org.openapitools"; + configPackage = "org.openapitools.configuration"; apiPackage = "org.openapitools.api"; modelPackage = "org.openapitools.model"; // cliOptions default redefinition need to be updated updateOption(CodegenConstants.ARTIFACT_ID, this.artifactId); + additionalProperties.put("openbrace", OPEN_BRACE); + additionalProperties.put("closebrace", CLOSE_BRACE); + // Use lists instead of arrays typeMapping.put("array", "kotlin.collections.List"); typeMapping.put("list", "kotlin.collections.List"); @@ -142,6 +174,7 @@ public KotlinSpringServerCodegen() { typeMapping.put("file", "org.springframework.core.io.Resource"); addOption(TITLE, "server title name or client service name", title); + addOption(CONFIG_PACKAGE, "configuration package for generated code", this.getConfigPackage()); addOption(BASE_PACKAGE, "base package (invokerPackage) for generated code", basePackage); addOption(SERVER_PORT, "configuration the port in which the sever is to run on", serverPort); addOption(CodegenConstants.MODEL_PACKAGE, "model package for generated code", modelPackage); @@ -158,6 +191,7 @@ public KotlinSpringServerCodegen() { addSwitch(SKIP_DEFAULT_INTERFACE, "Whether to skip generation of default implementations for interfaces", skipDefaultInterface); addSwitch(REACTIVE, "use coroutines for reactive behavior", reactive); addSwitch(INTERFACE_ONLY, "Whether to generate only API interface stubs without the server files.", interfaceOnly); + addSwitch(USE_FEIGN_CLIENT_URL, "Whether to generate Feign client with url parameter.", useFeignClientUrl); addSwitch(DELEGATE_PATTERN, "Whether to generate the server files using the delegate pattern", delegatePattern); addSwitch(USE_TAGS, "Whether to use tags for creating interface and controller class names", useTags); addSwitch(BEAN_QUALIFIERS, "Whether to add fully-qualifier class names as bean qualifiers in @Component and " + @@ -165,6 +199,8 @@ public KotlinSpringServerCodegen() { " (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); supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application."); + supportedLibraries.put(SPRING_CLOUD_LIBRARY, + "Spring-Cloud-Feign client with Spring-Boot auto-configured settings."); setLibrary(SPRING_BOOT); CliOption cliOpt = new CliOption(CodegenConstants.LIBRARY, CodegenConstants.LIBRARY_DESC); @@ -243,6 +279,14 @@ private boolean selectedDocumentationProviderRequiresSwaggerUiBootstrap() { getDocumentationProvider().equals(DocumentationProvider.SOURCE); } + public void setConfigPackage(String configPackage) { + this.configPackage = configPackage; + } + + public String getConfigPackage() { + return configPackage; + } + public String getBasePackage() { return this.basePackage; } @@ -300,6 +344,10 @@ public void setServiceInterface(boolean serviceInterface) { this.serviceInterface = serviceInterface; } + public void setUseFeignClientUrl(boolean useFeignClientUrl) { + this.useFeignClientUrl = useFeignClientUrl; + } + public boolean getServiceImplementation() { return this.serviceImplementation; } @@ -454,6 +502,12 @@ public void processOpts() { LOGGER.info("Set base package to invoker package ({})", basePackage); } + if (additionalProperties.containsKey(CONFIG_PACKAGE)) { + this.setConfigPackage((String) additionalProperties.get(CONFIG_PACKAGE)); + } else { + additionalProperties.put(CONFIG_PACKAGE, configPackage); + } + if (additionalProperties.containsKey(BASE_PACKAGE)) { this.setBasePackage((String) additionalProperties.get(BASE_PACKAGE)); } else { @@ -504,10 +558,15 @@ public void processOpts() { } writePropertyBack(SKIP_DEFAULT_INTERFACE, skipDefaultInterface); - if (additionalProperties.containsKey(REACTIVE) && library.equals(SPRING_BOOT)) { - this.setReactive(convertPropertyToBoolean(REACTIVE)); - // spring webflux doesn't support @ControllerAdvice - this.setExceptionHandler(false); + if (additionalProperties.containsKey(REACTIVE)) { + if (SPRING_CLOUD_LIBRARY.equals(library)) { + throw new IllegalArgumentException("Currently, reactive option doesn't supported by Spring Cloud"); + } + if (library.equals(SPRING_BOOT)) { + this.setReactive(convertPropertyToBoolean(REACTIVE)); + // spring webflux doesn't support @ControllerAdvice + this.setExceptionHandler(false); + } } writePropertyBack(REACTIVE, reactive); writePropertyBack(EXCEPTION_HANDLER, exceptionHandler); @@ -521,6 +580,15 @@ public void processOpts() { this.setInterfaceOnly(Boolean.parseBoolean(additionalProperties.get(INTERFACE_ONLY).toString())); } + if (library.equals(SPRING_CLOUD_LIBRARY)) { + this.setInterfaceOnly(true); + } + + if (additionalProperties.containsKey(USE_FEIGN_CLIENT_URL)) { + this.setUseFeignClientUrl(Boolean.parseBoolean(additionalProperties.get(USE_FEIGN_CLIENT_URL).toString())); + } + writePropertyBack(USE_FEIGN_CLIENT_URL, useFeignClientUrl); + if (additionalProperties.containsKey(DELEGATE_PATTERN)) { this.setDelegatePattern(Boolean.parseBoolean(additionalProperties.get(DELEGATE_PATTERN).toString())); } @@ -557,11 +625,6 @@ public void processOpts() { apiTestTemplateFiles.put("api_test.mustache", ".kt"); } - if (SPRING_BOOT.equals(library)) { - supportingFiles.add(new SupportingFile("apiUtil.mustache", - (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiUtil.kt")); - } - if (this.serviceInterface) { apiTemplateFiles.put("service.mustache", "Service.kt"); } else if (this.serviceImplementation) { @@ -579,13 +642,17 @@ public void processOpts() { supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); - if (this.exceptionHandler) { + if (this.exceptionHandler && !library.equals(SPRING_CLOUD_LIBRARY)) { supportingFiles.add(new SupportingFile("exceptions.mustache", sanitizeDirectory(sourceFolder + File.separator + apiPackage), "Exceptions.kt")); } if (library.equals(SPRING_BOOT)) { LOGGER.info("Setup code generator for Kotlin Spring Boot"); + + supportingFiles.add(new SupportingFile("apiUtil.mustache", + (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiUtil.kt")); + if (isUseSpringBoot3()) { supportingFiles.add(new SupportingFile("pom-sb3.mustache", "", "pom.xml")); } else { @@ -621,7 +688,36 @@ public void processOpts() { } } - if (!reactive) { + if (library.equals(SPRING_CLOUD_LIBRARY)) { + LOGGER.info("Setup code generator for Kotlin Spring Cloud Client"); + + if (isUseSpringBoot3()) { + supportingFiles.add(new SupportingFile("pom-sb3.mustache", "pom.xml")); + } else { + supportingFiles.add(new SupportingFile("pom.mustache", "pom.xml")); + } + + if (this.gradleBuildFile) { + if (isUseSpringBoot3()) { + supportingFiles.add(new SupportingFile("buildGradle-sb3-Kts.mustache", "build.gradle.kts")); + } else { + supportingFiles.add(new SupportingFile("buildGradleKts.mustache", "build.gradle.kts")); + } + supportingFiles.add(new SupportingFile("settingsGradle.mustache", "settings.gradle")); + } + + supportingFiles.add(new SupportingFile("apiKeyRequestInterceptor.mustache", + (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), + "ApiKeyRequestInterceptor.kt")); + supportingFiles.add(new SupportingFile("clientConfiguration.mustache", + (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), + "ClientConfiguration.kt")); + apiTemplateFiles.put("apiClient.mustache", "Client.kt"); + + apiTestTemplateFiles.clear(); + } + + if (!reactive && !library.equals(SPRING_CLOUD_LIBRARY)) { if (DocumentationProvider.SPRINGFOX.equals(getDocumentationProvider())) { supportingFiles.add(new SupportingFile("springfoxDocumentationConfig.mustache", (sourceFolder + File.separator + basePackage).replace(".", java.io.File.separator), diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/README.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/README.mustache new file mode 100644 index 000000000000..3550f428c71c --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/README.mustache @@ -0,0 +1,83 @@ +{{^interfaceOnly}} +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +### Maven users + +Add this dependency to your project's POM: + +```xml + + {{{groupId}}} + {{{artifactId}}} + {{{artifactVersion}}} + compile + +``` + +### Gradle users + +Add this dependency to your project's build file: + +```groovy +compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" +``` + +### Others + +At first generate the JAR by executing: + +mvn package + +Then manually install the following JARs: + +* target/{{{artifactId}}}-{{{artifactVersion}}}.jar +* target/lib/*.jar +{{/interfaceOnly}} +{{#interfaceOnly}} +# OpenAPI generated API stub + +Spring Framework stub + + +## Overview +This code was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. +By using the [OpenAPI-Spec](https://openapis.org), you can easily generate an API stub. +This is an example of building API stub interfaces in Java using the Spring framework. + +The stubs generated can be used in your existing Spring-MVC or Spring-Boot application to create controller endpoints +by adding ```@Controller``` classes that implement the interface. Eg: +```java +@Controller +public class PetController implements PetApi { +// implement all PetApi methods +} +``` + +You can also use the interface to create [Spring-Cloud Feign clients](http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign-inheritance).Eg: +```java +@FeignClient(name="pet", url="http://petstore.swagger.io/v2") +public interface PetClient extends PetApi { + +} +``` +{{/interfaceOnly}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/apiClient.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/apiClient.mustache new file mode 100644 index 000000000000..e900e8b5357b --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/apiClient.mustache @@ -0,0 +1,11 @@ +package {{package}} + +import org.springframework.cloud.openfeign.FeignClient +import {{configPackage}}.ClientConfiguration + +@FeignClient( + name="\${{openbrace}}{{classVarName}}.name:{{classVarName}}{{closebrace}}", + {{#useFeignClientUrl}}url="\${{openbrace}}{{classVarName}}.url:{{basePath}}{{closebrace}}", {{/useFeignClientUrl}} + configuration = [ClientConfiguration::class] +) +interface {{classname}}Client : {{classname}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/apiKeyRequestInterceptor.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/apiKeyRequestInterceptor.mustache new file mode 100644 index 000000000000..86bd615ccae6 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/apiKeyRequestInterceptor.mustache @@ -0,0 +1,19 @@ +package {{configPackage}} + +import feign.RequestInterceptor +import feign.RequestTemplate + +class ApiKeyRequestInterceptor( + private val location: String, + private val name: String, + private val value: String, +) : RequestInterceptor { + + override fun apply(requestTemplate: RequestTemplate) { + if (location == "header") { + requestTemplate.header(name, value) + } else if (location == "query") { + requestTemplate.query(name, value) + } + } +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/buildGradle-sb3-Kts.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/buildGradle-sb3-Kts.mustache new file mode 100644 index 000000000000..1bf4d3130667 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/buildGradle-sb3-Kts.mustache @@ -0,0 +1,68 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +group = "{{groupId}}" +version = "{{artifactVersion}}" +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" +} + +tasks.getByName("bootJar") { + enabled = false +} + +tasks.getByName("jar") { + enabled = true +} + +dependencyManagement { + imports { + mavenBom("org.springframework.cloud:spring-cloud-dependencies:2021.0.5") + } +} + +dependencies { +{{#reactive}} val kotlinxCoroutinesVersion = "1.6.1" +{{/reactive}} implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation("org.jetbrains.kotlin:kotlin-reflect"){{^reactive}} + implementation("org.springframework.boot:spring-boot-starter-web"){{/reactive}}{{#reactive}} + implementation("org.springframework.boot:spring-boot-starter-webflux") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$kotlinxCoroutinesVersion"){{/reactive}}{{#springDocDocumentationProvider}}{{#useSwaggerUI}} + implementation("org.springdoc:springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-ui:2.0.0-M5"){{/useSwaggerUI}}{{^useSwaggerUI}} + implementation("org.springdoc:springdoc-openapi-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-core:2.0.0-M5"){{/useSwaggerUI}}{{/springDocDocumentationProvider}}{{#springFoxDocumentationProvider}} + implementation("io.springfox:springfox-swagger2:2.9.2"){{/springFoxDocumentationProvider}}{{#useSwaggerUI}}{{^springDocDocumentationProvider}} + implementation("org.webjars:swagger-ui:4.10.3") + implementation("org.webjars:webjars-locator-core"){{/springDocDocumentationProvider}}{{/useSwaggerUI}}{{^springFoxDocumentationProvider}}{{^springDocDocumentationProvider}}{{#swagger1AnnotationLibrary}} + implementation("io.swagger:swagger-annotations:1.6.6"){{/swagger1AnnotationLibrary}}{{#swagger2AnnotationLibrary}} + implementation("io.swagger.core.v3:swagger-annotations:2.2.0"){{/swagger2AnnotationLibrary}}{{/springDocDocumentationProvider}}{{/springFoxDocumentationProvider}} + + 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("org.springframework.cloud:spring-cloud-starter-openfeign"){{#hasAuthMethods}} + implementation("org.springframework.cloud:spring-cloud-starter-oauth2:2.2.5.RELEASE"){{/hasAuthMethods}} + +{{#useBeanValidation}} + implementation("jakarta.validation:jakarta.validation-api"){{/useBeanValidation}} + implementation("jakarta.annotation:jakarta.annotation-api:2.1.0") + +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/buildGradleKts.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/buildGradleKts.mustache new file mode 100644 index 000000000000..b1a7e08ce4b9 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/buildGradleKts.mustache @@ -0,0 +1,75 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath("org.springframework.boot:spring-boot-gradle-plugin:2.6.7") + } +} + +group = "{{groupId}}" +version = "{{artifactVersion}}" + +repositories { + mavenCentral() +} + +tasks.withType { + kotlinOptions.jvmTarget = "1.8" +} + +plugins { + val kotlinVersion = "1.6.21" + 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 "2.6.7" + id("io.spring.dependency-management") version "1.0.11.RELEASE" +} + +tasks.getByName("bootJar") { + enabled = false +} + +tasks.getByName("jar") { + enabled = true +} + +dependencyManagement { + imports { + mavenBom("org.springframework.cloud:spring-cloud-dependencies:2021.0.5") + } +} + +dependencies { +{{#reactive}} val kotlinxCoroutinesVersion = "1.6.1" +{{/reactive}} implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation("org.jetbrains.kotlin:kotlin-reflect"){{^reactive}} + implementation("org.springframework.boot:spring-boot-starter-web"){{/reactive}}{{#reactive}} + implementation("org.springframework.boot:spring-boot-starter-webflux") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$kotlinxCoroutinesVersion"){{/reactive}}{{#springDocDocumentationProvider}}{{#useSwaggerUI}} + implementation("org.springdoc:springdoc-openapi-{{#reactive}}webflux-{{/reactive}}ui:1.6.8"){{/useSwaggerUI}}{{^useSwaggerUI}} + implementation("org.springdoc:springdoc-openapi-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-core:1.6.8"){{/useSwaggerUI}}{{/springDocDocumentationProvider}}{{#springFoxDocumentationProvider}} + implementation("io.springfox:springfox-swagger2:2.9.2"){{/springFoxDocumentationProvider}}{{#useSwaggerUI}}{{^springDocDocumentationProvider}} + implementation("org.webjars:swagger-ui:4.10.3") + implementation("org.webjars:webjars-locator-core"){{/springDocDocumentationProvider}}{{/useSwaggerUI}}{{^springFoxDocumentationProvider}}{{^springDocDocumentationProvider}}{{#swagger1AnnotationLibrary}} + implementation("io.swagger:swagger-annotations:1.6.6"){{/swagger1AnnotationLibrary}}{{#swagger2AnnotationLibrary}} + implementation("io.swagger.core.v3:swagger-annotations:2.2.0"){{/swagger2AnnotationLibrary}}{{/springDocDocumentationProvider}}{{/springFoxDocumentationProvider}} + + 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("org.springframework.cloud:spring-cloud-starter-openfeign"){{#hasAuthMethods}} + implementation("org.springframework.cloud:spring-cloud-starter-oauth2:2.2.5.RELEASE"){{/hasAuthMethods}} + +{{#useBeanValidation}} + implementation("jakarta.validation:jakarta.validation-api"){{/useBeanValidation}} + implementation("jakarta.annotation:jakarta.annotation-api:2.1.0") + +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/clientConfiguration.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/clientConfiguration.mustache new file mode 100644 index 000000000000..c23c5ee12370 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/clientConfiguration.mustache @@ -0,0 +1,132 @@ +package {{configPackage}} + +{{#authMethods}} +{{#isBasic}} +import feign.auth.BasicAuthRequestInterceptor +{{/isBasic}} +{{#-first}} +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +{{/-first}} +{{#isOAuth}} +import org.springframework.boot.context.properties.ConfigurationProperties +{{/isOAuth}} +{{/authMethods}} +import org.springframework.boot.context.properties.EnableConfigurationProperties +{{#authMethods}} +{{#-first}} +import org.springframework.context.annotation.Bean +{{/-first}} +{{/authMethods}} +import org.springframework.context.annotation.Configuration +{{#authMethods}} +{{#isOAuth}} +import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor +import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext +import org.springframework.security.oauth2.client.OAuth2ClientContext +{{#isApplication}} +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails +{{/isApplication}} +{{#isCode}} +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails +{{/isCode}} +{{#isImplicit}} +import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails +{{/isImplicit}} +{{#isPassword}} +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails +{{/isPassword}} +{{/isOAuth}} +{{/authMethods}} + +@Configuration +@EnableConfigurationProperties +class ClientConfiguration { + + {{#authMethods}} + {{#isBasic}} + @Value("\${{openbrace}}{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.username:{{closebrace}}") + private lateinit var {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Username: String + + @Value("\${{openbrace}}{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.password:{{closebrace}}") + private lateinit var {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Password: String + + @Bean + @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.username") + fun {{{name}}}RequestInterceptor(): BasicAuthRequestInterceptor { + return BasicAuthRequestInterceptor(this.{{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Username, this.{{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Password) + } + + {{/isBasic}} + {{#isApiKey}} + @Value("\${{openbrace}}{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.key:{{closebrace}}") + private lateinit var {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Key: String + + @Bean + @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.key") + fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}RequestInterceptor(): ApiKeyRequestInterceptor { + return ApiKeyRequestInterceptor({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{{keyParamName}}}", this.{{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}Key) + } + + {{/isApiKey}} + {{#isOAuth}} + @Bean + @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") + fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}RequestInterceptor(oAuth2ClientContext: OAuth2ClientContext): OAuth2FeignRequestInterceptor { + return OAuth2FeignRequestInterceptor(oAuth2ClientContext, {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}ResourceDetails()) + } + + @Bean + @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") + fun oAuth2ClientContext(): OAuth2ClientContext { + return DefaultOAuth2ClientContext() + } + + {{#isCode}} + @Bean + @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") + @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}") + fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}ResourceDetails(): AuthorizationCodeResourceDetails { + val details = AuthorizationCodeResourceDetails() + details.accessTokenUri = "{{{tokenUrl}}}" + details.userAuthorizationUri = "{{{authorizationUrl}}}" + return details + } + + {{/isCode}} + {{#isPassword}} + @Bean + @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") + @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}") + fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}ResourceDetails(): ResourceOwnerPasswordResourceDetails { + val details = ResourceOwnerPasswordResourceDetails() + details.accessTokenUri = "{{{tokenUrl}}}" + return details + } + + {{/isPassword}} + {{#isApplication}} + @Bean + @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") + @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}") + fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}ResourceDetails(): ClientCredentialsResourceDetails { + val details = ClientCredentialsResourceDetails() + details.accessTokenUri = "{{{tokenUrl}}}" + return details + } + + {{/isApplication}} + {{#isImplicit}} + @Bean + @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") + @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}") + fun {{#lambda.camelcase}}{{{name}}}{{/lambda.camelcase}}ResourceDetails(): ImplicitResourceDetails { + val details = ImplicitResourceDetails() + details.userAuthorizationUri= "{{{authorizationUrl}}}" + return details + } + + {{/isImplicit}} + {{/isOAuth}} + {{/authMethods}} +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/pom-sb3.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/pom-sb3.mustache new file mode 100644 index 000000000000..14621302900d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/pom-sb3.mustache @@ -0,0 +1,233 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{#reactive}} + 1.6.1 + {{/reactive}}{{#springDocDocumentationProvider}}{{#useSwaggerUI}} + 2.0.2 + {{/useSwaggerUI}}{{/springDocDocumentationProvider}}{{#springFoxDocumentationProvider}} + 2.9.2 + {{/springFoxDocumentationProvider}}{{#useSwaggerUI}}{{^springDocDocumentationProvider}} + 4.15.5 + {{/springDocDocumentationProvider}}{{/useSwaggerUI}}{{^springFoxDocumentationProvider}}{{^springDocDocumentationProvider}}{{#swagger1AnnotationLibrary}} + 1.6.6 + {{/swagger1AnnotationLibrary}}{{#swagger2AnnotationLibrary}} + 2.2.7 + {{/swagger2AnnotationLibrary}}{{/springDocDocumentationProvider}}{{/springFoxDocumentationProvider}} + 3.0.2 + 2.1.0 + 1.7.10 + + 1.7.10 + UTF-8 + + + org.springframework.boot + spring-boot-starter-parent + 3.0.2 + + + + + org.springframework.cloud + spring-cloud-starter-parent + 2021.0.5 + pom + import + + + + + + repository.spring.milestone + Spring Milestone Repository + https://repo.spring.io/milestone + + + + + spring-milestones + https://repo.spring.io/milestone + + + + ${project.basedir}/src/main/kotlin + {{^interfaceOnly}} + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + {{/interfaceOnly}} + + 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} + {{^reactive}} + + org.springframework.boot + spring-boot-starter-web + {{/reactive}}{{#reactive}} + + org.springframework.boot + spring-boot-starter-webflux + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + ${kotlinx-coroutines.version} + + + org.jetbrains.kotlinx + kotlinx-coroutines-reactor + ${kotlinx-coroutines.version} + {{/reactive}} + + {{#springDocDocumentationProvider}} + {{#useSwaggerUI}} + + org.springdoc + springdoc-openapi-starter-{{#reactive}} + webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-ui + + ${springdoc-openapi.version} + {{/useSwaggerUI}}{{^useSwaggerUI}} + + org.springdoc + springdoc-openapi-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-core + + ${springdoc-openapi.version} + {{/useSwaggerUI}}{{/springDocDocumentationProvider}}{{#springFoxDocumentationProvider}} + + + io.springfox + springfox-swagger2 + ${springfox-swagger2.version} + {{/springFoxDocumentationProvider}}{{#useSwaggerUI}}{{^springDocDocumentationProvider}} + + org.webjars + swagger-ui + ${swagger-ui.version} + + + org.webjars + webjars-locator-core + {{/springDocDocumentationProvider}}{{/useSwaggerUI}}{{^springFoxDocumentationProvider}}{{^springDocDocumentationProvider}}{{#swagger1AnnotationLibrary}} + + io.swagger + swagger-annotations + ${swagger-annotations.version} + {{/swagger1AnnotationLibrary}}{{#swagger2AnnotationLibrary}} + + io.swagger.core.v3 + swagger-annotations + ${swagger-annotations.version} + {{/swagger2AnnotationLibrary}}{{/springDocDocumentationProvider}}{{/springFoxDocumentationProvider}} + + + + com.google.code.findbugs + jsr305 + ${findbugs-jsr305.version} + + + org.springframework.cloud + spring-cloud-starter-openfeign + + {{#hasAuthMethods}} + + org.springframework.cloud + spring-cloud-starter-oauth2 + {{^parentOverridden}} + 2.2.5.RELEASE + {{/parentOverridden}} + + {{/hasAuthMethods}} + + 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 + +{{#useBeanValidation}} + + + jakarta.validation + jakarta.validation-api + {{/useBeanValidation}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation.version} + provided + + + org.jetbrains.kotlin + kotlin-test-junit5 + ${kotlin-test-junit5.version} + test + + + diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/pom.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/pom.mustache new file mode 100644 index 000000000000..ddab15182b67 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/pom.mustache @@ -0,0 +1,210 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{#reactive}} + 1.6.1{{/reactive}}{{#springDocDocumentationProvider}}{{#useSwaggerUI}} + 1.6.8{{/useSwaggerUI}}{{/springDocDocumentationProvider}}{{#springFoxDocumentationProvider}} + 2.9.2{{/springFoxDocumentationProvider}}{{#useSwaggerUI}}{{^springDocDocumentationProvider}} + 4.10.3{{/springDocDocumentationProvider}}{{/useSwaggerUI}}{{^springFoxDocumentationProvider}}{{^springDocDocumentationProvider}}{{#swagger1AnnotationLibrary}} + 1.6.6{{/swagger1AnnotationLibrary}}{{#swagger2AnnotationLibrary}} + 2.2.0{{/swagger2AnnotationLibrary}}{{/springDocDocumentationProvider}}{{/springFoxDocumentationProvider}} + 3.0.2 + 2.1.0 + 1.6.21 + + 1.6.21 + UTF-8 + + + org.springframework.boot + spring-boot-starter-parent + 2.6.7 + + + + + org.springframework.cloud + spring-cloud-starter-parent + 2021.0.5 + pom + import + + + + + ${project.basedir}/src/main/kotlin + {{^interfaceOnly}} + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + {{/interfaceOnly}} + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + spring + + 1.8 + + + + 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} + {{^reactive}} + + org.springframework.boot + spring-boot-starter-web + {{/reactive}}{{#reactive}} + + org.springframework.boot + spring-boot-starter-webflux + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + ${kotlinx-coroutines.version} + + + org.jetbrains.kotlinx + kotlinx-coroutines-reactor + ${kotlinx-coroutines.version} + {{/reactive}} + +{{#springDocDocumentationProvider}} + {{#useSwaggerUI}} + + org.springdoc + springdoc-openapi-{{#reactive}}webflux-{{/reactive}}ui + ${springdoc-openapi.version} + {{/useSwaggerUI}}{{^useSwaggerUI}} + + org.springdoc + springdoc-openapi-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-core + ${springdoc-openapi.version} + {{/useSwaggerUI}}{{/springDocDocumentationProvider}}{{#springFoxDocumentationProvider}} + + + io.springfox + springfox-swagger2 + ${springfox-swagger2.version} + {{/springFoxDocumentationProvider}}{{#useSwaggerUI}}{{^springDocDocumentationProvider}} + + org.webjars + swagger-ui + ${swagger-ui.version} + + + org.webjars + webjars-locator-core + {{/springDocDocumentationProvider}}{{/useSwaggerUI}}{{^springFoxDocumentationProvider}}{{^springDocDocumentationProvider}}{{#swagger1AnnotationLibrary}} + + io.swagger + swagger-annotations + ${swagger-annotations.version} + {{/swagger1AnnotationLibrary}}{{#swagger2AnnotationLibrary}} + + io.swagger.core.v3 + swagger-annotations + ${swagger-annotations.version} + {{/swagger2AnnotationLibrary}}{{/springDocDocumentationProvider}}{{/springFoxDocumentationProvider}} + + + + com.google.code.findbugs + jsr305 + ${findbugs-jsr305.version} + + + org.springframework.cloud + spring-cloud-starter-openfeign + + {{#hasAuthMethods}} + + org.springframework.cloud + spring-cloud-starter-oauth2 + {{^parentOverridden}} + 2.2.5.RELEASE + {{/parentOverridden}} + + {{/hasAuthMethods}} + + 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 + +{{#useBeanValidation}} + + + jakarta.validation + jakarta.validation-api + {{/useBeanValidation}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation.version} + provided + + + org.jetbrains.kotlin + kotlin-test-junit5 + ${kotlin-test-junit5.version} + test + + + diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/settingsGradle.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/settingsGradle.mustache new file mode 100644 index 000000000000..fd23a36b9038 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/libraries/spring-cloud/settingsGradle.mustache @@ -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 = "{{artifactId}}" diff --git a/samples/client/petstore/kotlin-spring-cloud/.openapi-generator-ignore b/samples/client/petstore/kotlin-spring-cloud/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/.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/client/petstore/kotlin-spring-cloud/.openapi-generator/FILES b/samples/client/petstore/kotlin-spring-cloud/.openapi-generator/FILES new file mode 100644 index 000000000000..cb11aec76f7c --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/.openapi-generator/FILES @@ -0,0 +1,18 @@ +README.md +build.gradle.kts +pom.xml +settings.gradle +src/main/kotlin/org/openapitools/api/PetApi.kt +src/main/kotlin/org/openapitools/api/PetApiClient.kt +src/main/kotlin/org/openapitools/api/StoreApi.kt +src/main/kotlin/org/openapitools/api/StoreApiClient.kt +src/main/kotlin/org/openapitools/api/UserApi.kt +src/main/kotlin/org/openapitools/api/UserApiClient.kt +src/main/kotlin/org/openapitools/configuration/ApiKeyRequestInterceptor.kt +src/main/kotlin/org/openapitools/configuration/ClientConfiguration.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/client/petstore/kotlin-spring-cloud/.openapi-generator/VERSION b/samples/client/petstore/kotlin-spring-cloud/.openapi-generator/VERSION new file mode 100644 index 000000000000..ba8a874deab9 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/.openapi-generator/VERSION @@ -0,0 +1 @@ +6.6.0-SNAPSHOT \ No newline at end of file diff --git a/samples/client/petstore/kotlin-spring-cloud/README.md b/samples/client/petstore/kotlin-spring-cloud/README.md new file mode 100644 index 000000000000..a462be951ace --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/README.md @@ -0,0 +1,26 @@ +# OpenAPI generated API stub + +Spring Framework stub + + +## Overview +This code was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. +By using the [OpenAPI-Spec](https://openapis.org), you can easily generate an API stub. +This is an example of building API stub interfaces in Java using the Spring framework. + +The stubs generated can be used in your existing Spring-MVC or Spring-Boot application to create controller endpoints +by adding ```@Controller``` classes that implement the interface. Eg: +```java +@Controller +public class PetController implements PetApi { +// implement all PetApi methods +} +``` + +You can also use the interface to create [Spring-Cloud Feign clients](http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign-inheritance).Eg: +```java +@FeignClient(name="pet", url="http://petstore.swagger.io/v2") +public interface PetClient extends PetApi { + +} +``` diff --git a/samples/client/petstore/kotlin-spring-cloud/build.gradle.kts b/samples/client/petstore/kotlin-spring-cloud/build.gradle.kts new file mode 100644 index 000000000000..b2c90c440cfb --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/build.gradle.kts @@ -0,0 +1,63 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath("org.springframework.boot:spring-boot-gradle-plugin:2.6.7") + } +} + +group = "org.openapitools" +version = "1.0.0" + +repositories { + mavenCentral() +} + +tasks.withType { + kotlinOptions.jvmTarget = "1.8" +} + +plugins { + val kotlinVersion = "1.6.21" + 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 "2.6.7" + id("io.spring.dependency-management") version "1.0.11.RELEASE" +} + +tasks.getByName("bootJar") { + enabled = false +} + +tasks.getByName("jar") { + enabled = true +} + +dependencyManagement { + imports { + mavenBom("org.springframework.cloud:spring-cloud-dependencies:2021.0.5") + } +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation("org.jetbrains.kotlin:kotlin-reflect") + implementation("org.springframework.boot:spring-boot-starter-web") + + 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("org.springframework.cloud:spring-cloud-starter-openfeign") + implementation("org.springframework.cloud:spring-cloud-starter-oauth2:2.2.5.RELEASE") + + implementation("jakarta.validation:jakarta.validation-api") + implementation("jakarta.annotation:jakarta.annotation-api:2.1.0") + +} diff --git a/samples/client/petstore/kotlin-spring-cloud/pom.xml b/samples/client/petstore/kotlin-spring-cloud/pom.xml new file mode 100644 index 000000000000..9f53a2f0ae0c --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/pom.xml @@ -0,0 +1,138 @@ + + 4.0.0 + org.openapitools + openapi-spring + jar + openapi-spring + 1.0.0 + + 3.0.2 + 2.1.0 + 1.6.21 + + 1.6.21 + UTF-8 + + + org.springframework.boot + spring-boot-starter-parent + 2.6.7 + + + + + org.springframework.cloud + spring-cloud-starter-parent + 2021.0.5 + pom + import + + + + + ${project.basedir}/src/main/kotlin + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + spring + + 1.8 + + + + 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 + + + + + + + com.google.code.findbugs + jsr305 + ${findbugs-jsr305.version} + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + org.springframework.cloud + spring-cloud-starter-oauth2 + 2.2.5.RELEASE + + + 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/client/petstore/kotlin-spring-cloud/settings.gradle b/samples/client/petstore/kotlin-spring-cloud/settings.gradle new file mode 100644 index 000000000000..14844905cd40 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/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/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/PetApi.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/PetApi.kt new file mode 100644 index 000000000000..f6e5790f710a --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/PetApi.kt @@ -0,0 +1,117 @@ +/** + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (6.6.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 org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity + +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 javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid + +import kotlin.collections.List +import kotlin.collections.Map + +@Validated +@RequestMapping("\${api.base-path:/v2}") +interface PetApi { + + + @RequestMapping( + method = [RequestMethod.POST], + value = ["/pet"], + produces = ["application/xml", "application/json"], + consumes = ["application/json", "application/xml"] + ) + fun addPet( @Valid @RequestBody pet: Pet): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.DELETE], + value = ["/pet/{petId}"] + ) + fun deletePet( @PathVariable("petId") petId: kotlin.Long, @RequestHeader(value = "api_key", required = false) apiKey: kotlin.String?): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.GET], + value = ["/pet/findByStatus"], + produces = ["application/xml", "application/json"] + ) + fun findPetsByStatus(@NotNull @Valid @RequestParam(value = "status", required = true) status: kotlin.collections.List): ResponseEntity> { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.GET], + value = ["/pet/findByTags"], + produces = ["application/xml", "application/json"] + ) + fun findPetsByTags(@NotNull @Valid @RequestParam(value = "tags", required = true) tags: kotlin.collections.List): ResponseEntity> { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.GET], + value = ["/pet/{petId}"], + produces = ["application/xml", "application/json"] + ) + fun getPetById( @PathVariable("petId") petId: kotlin.Long): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.PUT], + value = ["/pet"], + produces = ["application/xml", "application/json"], + consumes = ["application/json", "application/xml"] + ) + fun updatePet( @Valid @RequestBody pet: Pet): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.POST], + value = ["/pet/{petId}"], + consumes = ["application/x-www-form-urlencoded"] + ) + fun updatePetWithForm( @PathVariable("petId") petId: kotlin.Long, @RequestParam(value = "name", required = false) name: kotlin.String? , @RequestParam(value = "status", required = false) status: kotlin.String? ): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.POST], + value = ["/pet/{petId}/uploadImage"], + produces = ["application/json"], + consumes = ["multipart/form-data"] + ) + fun uploadFile( @PathVariable("petId") petId: kotlin.Long, @RequestParam(value = "additionalMetadata", required = false) additionalMetadata: kotlin.String? , @Valid @RequestPart("file") file: org.springframework.core.io.Resource?): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } +} diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/PetApiClient.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/PetApiClient.kt new file mode 100644 index 000000000000..8373f9aa9393 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/PetApiClient.kt @@ -0,0 +1,11 @@ +package org.openapitools.api + +import org.springframework.cloud.openfeign.FeignClient +import org.openapitools.configuration.ClientConfiguration + +@FeignClient( + name="\${pet.name:pet}", + url="\${pet.url:http://petstore.swagger.io/v2}", + configuration = [ClientConfiguration::class] +) +interface PetApiClient : PetApi diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/StoreApi.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/StoreApi.kt new file mode 100644 index 000000000000..a05822c7b3f8 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/StoreApi.kt @@ -0,0 +1,74 @@ +/** + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (6.6.0-SNAPSHOT). + * https://openapi-generator.tech + * Do not edit the class manually. +*/ +package org.openapitools.api + +import org.openapitools.model.Order +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity + +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 javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid + +import kotlin.collections.List +import kotlin.collections.Map + +@Validated +@RequestMapping("\${api.base-path:/v2}") +interface StoreApi { + + + @RequestMapping( + method = [RequestMethod.DELETE], + value = ["/store/order/{orderId}"] + ) + fun deleteOrder( @PathVariable("orderId") orderId: kotlin.String): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.GET], + value = ["/store/inventory"], + produces = ["application/json"] + ) + fun getInventory(): ResponseEntity> { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.GET], + value = ["/store/order/{orderId}"], + produces = ["application/xml", "application/json"] + ) + fun getOrderById(@Min(1L) @Max(5L) @PathVariable("orderId") orderId: kotlin.Long): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.POST], + value = ["/store/order"], + produces = ["application/xml", "application/json"], + consumes = ["application/json"] + ) + fun placeOrder( @Valid @RequestBody order: Order): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } +} diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/StoreApiClient.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/StoreApiClient.kt new file mode 100644 index 000000000000..e3d21e46f0c7 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/StoreApiClient.kt @@ -0,0 +1,11 @@ +package org.openapitools.api + +import org.springframework.cloud.openfeign.FeignClient +import org.openapitools.configuration.ClientConfiguration + +@FeignClient( + name="\${store.name:store}", + url="\${store.url:http://petstore.swagger.io/v2}", + configuration = [ClientConfiguration::class] +) +interface StoreApiClient : StoreApi diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/UserApi.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/UserApi.kt new file mode 100644 index 000000000000..fc4ff28a43fa --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/UserApi.kt @@ -0,0 +1,112 @@ +/** + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (6.6.0-SNAPSHOT). + * https://openapi-generator.tech + * Do not edit the class manually. +*/ +package org.openapitools.api + +import org.openapitools.model.User +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity + +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 javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid + +import kotlin.collections.List +import kotlin.collections.Map + +@Validated +@RequestMapping("\${api.base-path:/v2}") +interface UserApi { + + + @RequestMapping( + method = [RequestMethod.POST], + value = ["/user"], + consumes = ["application/json"] + ) + fun createUser( @Valid @RequestBody user: User): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.POST], + value = ["/user/createWithArray"], + consumes = ["application/json"] + ) + fun createUsersWithArrayInput( @Valid @RequestBody user: kotlin.collections.List): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.POST], + value = ["/user/createWithList"], + consumes = ["application/json"] + ) + fun createUsersWithListInput( @Valid @RequestBody user: kotlin.collections.List): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.DELETE], + value = ["/user/{username}"] + ) + fun deleteUser( @PathVariable("username") username: kotlin.String): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.GET], + value = ["/user/{username}"], + produces = ["application/xml", "application/json"] + ) + fun getUserByName( @PathVariable("username") username: kotlin.String): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.GET], + value = ["/user/login"], + produces = ["application/xml", "application/json"] + ) + fun loginUser(@NotNull @Pattern(regexp="^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$") @Valid @RequestParam(value = "username", required = true) username: kotlin.String,@NotNull @Valid @RequestParam(value = "password", required = true) password: kotlin.String): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.GET], + value = ["/user/logout"] + ) + fun logoutUser(): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } + + + @RequestMapping( + method = [RequestMethod.PUT], + value = ["/user/{username}"], + consumes = ["application/json"] + ) + fun updateUser( @PathVariable("username") username: kotlin.String, @Valid @RequestBody user: User): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } +} diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/UserApiClient.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/UserApiClient.kt new file mode 100644 index 000000000000..0d7af2aeaa3d --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/api/UserApiClient.kt @@ -0,0 +1,11 @@ +package org.openapitools.api + +import org.springframework.cloud.openfeign.FeignClient +import org.openapitools.configuration.ClientConfiguration + +@FeignClient( + name="\${user.name:user}", + url="\${user.url:http://petstore.swagger.io/v2}", + configuration = [ClientConfiguration::class] +) +interface UserApiClient : UserApi diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/configuration/ApiKeyRequestInterceptor.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/configuration/ApiKeyRequestInterceptor.kt new file mode 100644 index 000000000000..b9129a3b0074 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/configuration/ApiKeyRequestInterceptor.kt @@ -0,0 +1,19 @@ +package org.openapitools.configuration + +import feign.RequestInterceptor +import feign.RequestTemplate + +class ApiKeyRequestInterceptor( + private val location: String, + private val name: String, + private val value: String, +) : RequestInterceptor { + + override fun apply(requestTemplate: RequestTemplate) { + if (location == "header") { + requestTemplate.header(name, value) + } else if (location == "query") { + requestTemplate.query(name, value) + } + } +} diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/configuration/ClientConfiguration.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/configuration/ClientConfiguration.kt new file mode 100644 index 000000000000..8a2e2b4b7270 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/configuration/ClientConfiguration.kt @@ -0,0 +1,48 @@ +package org.openapitools.configuration + +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor +import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext +import org.springframework.security.oauth2.client.OAuth2ClientContext +import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails + +@Configuration +@EnableConfigurationProperties +class ClientConfiguration { + + @Bean + @ConditionalOnProperty("openapipetstore.security.petstore_auth.client-id") + fun petstoreAuthRequestInterceptor(oAuth2ClientContext: OAuth2ClientContext): OAuth2FeignRequestInterceptor { + return OAuth2FeignRequestInterceptor(oAuth2ClientContext, petstoreAuthResourceDetails()) + } + + @Bean + @ConditionalOnProperty("openapipetstore.security.petstore_auth.client-id") + fun oAuth2ClientContext(): OAuth2ClientContext { + return DefaultOAuth2ClientContext() + } + + @Bean + @ConditionalOnProperty("openapipetstore.security.petstore_auth.client-id") + @ConfigurationProperties("openapipetstore.security.petstore_auth") + fun petstoreAuthResourceDetails(): ImplicitResourceDetails { + val details = ImplicitResourceDetails() + details.userAuthorizationUri= "http://petstore.swagger.io/api/oauth/dialog" + return details + } + + @Value("\${openapipetstore.security.api_key.key:}") + private lateinit var apiKeyKey: String + + @Bean + @ConditionalOnProperty("openapipetstore.security.api_key.key") + fun apiKeyRequestInterceptor(): ApiKeyRequestInterceptor { + return ApiKeyRequestInterceptor("header", "api_key", this.apiKeyKey) + } + +} diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Category.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Category.kt new file mode 100644 index 000000000000..81d080e03d28 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Category.kt @@ -0,0 +1,29 @@ +package org.openapitools.model + +import java.util.Objects +import com.fasterxml.jackson.annotation.JsonProperty +import javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid + +/** + * A category for a pet + * @param id + * @param name + */ +data class Category( + + @get:JsonProperty("id") val id: kotlin.Long? = null, + + @get:Pattern(regexp="^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$") + @get:JsonProperty("name") val name: kotlin.String? = null +) { + +} + diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/ModelApiResponse.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/ModelApiResponse.kt new file mode 100644 index 000000000000..4b42c877edb9 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/ModelApiResponse.kt @@ -0,0 +1,31 @@ +package org.openapitools.model + +import java.util.Objects +import com.fasterxml.jackson.annotation.JsonProperty +import javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid + +/** + * Describes the result of uploading an image resource + * @param code + * @param type + * @param message + */ +data class ModelApiResponse( + + @get:JsonProperty("code") val code: kotlin.Int? = null, + + @get:JsonProperty("type") val type: kotlin.String? = null, + + @get:JsonProperty("message") val message: kotlin.String? = null +) { + +} + diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Order.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Order.kt new file mode 100644 index 000000000000..61814bda584b --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Order.kt @@ -0,0 +1,52 @@ +package org.openapitools.model + +import java.util.Objects +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.annotation.JsonValue +import javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid + +/** + * An order for a pets from the pet store + * @param id + * @param petId + * @param quantity + * @param shipDate + * @param status Order Status + * @param complete + */ +data class Order( + + @get:JsonProperty("id") val id: kotlin.Long? = null, + + @get:JsonProperty("petId") val petId: kotlin.Long? = null, + + @get:JsonProperty("quantity") val quantity: kotlin.Int? = null, + + @get:JsonProperty("shipDate") val shipDate: java.time.OffsetDateTime? = null, + + @get:JsonProperty("status") val status: Order.Status? = null, + + @get:JsonProperty("complete") val complete: kotlin.Boolean? = false +) { + + /** + * Order Status + * Values: placed,approved,delivered + */ + enum class Status(val value: kotlin.String) { + + @JsonProperty("placed") placed("placed"), + @JsonProperty("approved") approved("approved"), + @JsonProperty("delivered") delivered("delivered") + } + +} + diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Pet.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Pet.kt new file mode 100644 index 000000000000..dfd146015802 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Pet.kt @@ -0,0 +1,57 @@ +package org.openapitools.model + +import java.util.Objects +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.annotation.JsonValue +import org.openapitools.model.Category +import org.openapitools.model.Tag +import javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid + +/** + * A pet for sale in the pet store + * @param name + * @param photoUrls + * @param id + * @param category + * @param tags + * @param status pet status in the store + */ +data class Pet( + + @get:JsonProperty("name", required = true) val name: kotlin.String, + + @get:JsonProperty("photoUrls", required = true) val photoUrls: kotlin.collections.List, + + @get:JsonProperty("id") val id: kotlin.Long? = null, + + @field:Valid + @get:JsonProperty("category") val category: Category? = null, + + @field:Valid + @get:JsonProperty("tags") val tags: kotlin.collections.List? = null, + + @Deprecated(message = "") + @get:JsonProperty("status") val status: Pet.Status? = null +) { + + /** + * pet status in the store + * Values: available,pending,sold + */ + enum class Status(val value: kotlin.String) { + + @JsonProperty("available") available("available"), + @JsonProperty("pending") pending("pending"), + @JsonProperty("sold") sold("sold") + } + +} + diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Tag.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Tag.kt new file mode 100644 index 000000000000..0beafadd514c --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/Tag.kt @@ -0,0 +1,28 @@ +package org.openapitools.model + +import java.util.Objects +import com.fasterxml.jackson.annotation.JsonProperty +import javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid + +/** + * A tag for a pet + * @param id + * @param name + */ +data class Tag( + + @get:JsonProperty("id") val id: kotlin.Long? = null, + + @get:JsonProperty("name") val name: kotlin.String? = null +) { + +} + diff --git a/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/User.kt b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/User.kt new file mode 100644 index 000000000000..8780ff0d2f24 --- /dev/null +++ b/samples/client/petstore/kotlin-spring-cloud/src/main/kotlin/org/openapitools/model/User.kt @@ -0,0 +1,46 @@ +package org.openapitools.model + +import java.util.Objects +import com.fasterxml.jackson.annotation.JsonProperty +import javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid + +/** + * A User who is purchasing from the pet store + * @param id + * @param username + * @param firstName + * @param lastName + * @param email + * @param password + * @param phone + * @param userStatus User Status + */ +data class User( + + @get:JsonProperty("id") val id: kotlin.Long? = null, + + @get:JsonProperty("username") val username: kotlin.String? = null, + + @get:JsonProperty("firstName") val firstName: kotlin.String? = null, + + @get:JsonProperty("lastName") val lastName: kotlin.String? = null, + + @get:JsonProperty("email") val email: kotlin.String? = null, + + @get:JsonProperty("password") val password: kotlin.String? = null, + + @get:JsonProperty("phone") val phone: kotlin.String? = null, + + @get:JsonProperty("userStatus") val userStatus: kotlin.Int? = null +) { + +} +