From a8826816fb63ca01358540b2ac4ce68542e2a7fb Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 16 Sep 2019 22:47:28 +0800 Subject: [PATCH] test kotlin vertx in pom.xml (#3890) --- README.md | 3 +- docs/generators.md | 2 +- .../languages/KotlinVertxServerCodegen.java | 12 +- pom.xml | 1 + .../kotlin/vertx/.openapi-generator-ignore | 23 ++ .../kotlin/vertx/.openapi-generator/VERSION | 1 + .../server/petstore/kotlin/vertx/README.md | 81 +++++++ samples/server/petstore/kotlin/vertx/pom.xml | 190 ++++++++++++++++ .../server/api/model/ApiResponse.kt | 34 +++ .../openapitools/server/api/model/Category.kt | 32 +++ .../openapitools/server/api/model/Order.kt | 55 +++++ .../org/openapitools/server/api/model/Pet.kt | 61 +++++ .../org/openapitools/server/api/model/Tag.kt | 32 +++ .../org/openapitools/server/api/model/User.kt | 45 ++++ .../server/api/verticle/PetApi.kt | 70 ++++++ .../server/api/verticle/PetApiVerticle.kt | 19 ++ .../api/verticle/PetApiVertxProxyHandler.kt | 214 ++++++++++++++++++ .../server/api/verticle/StoreApi.kt | 57 +++++ .../server/api/verticle/StoreApiVerticle.kt | 19 ++ .../api/verticle/StoreApiVertxProxyHandler.kt | 125 ++++++++++ .../server/api/verticle/UserApi.kt | 69 ++++++ .../server/api/verticle/UserApiVerticle.kt | 19 ++ .../api/verticle/UserApiVertxProxyHandler.kt | 202 +++++++++++++++++ 23 files changed, 1359 insertions(+), 7 deletions(-) create mode 100644 samples/server/petstore/kotlin/vertx/.openapi-generator-ignore create mode 100644 samples/server/petstore/kotlin/vertx/.openapi-generator/VERSION create mode 100644 samples/server/petstore/kotlin/vertx/README.md create mode 100644 samples/server/petstore/kotlin/vertx/pom.xml create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/ApiResponse.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Category.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Order.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Pet.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Tag.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/User.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApi.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVerticle.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVertxProxyHandler.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApi.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApiVerticle.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApiVertxProxyHandler.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApi.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApiVerticle.kt create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApiVertxProxyHandler.kt diff --git a/README.md b/README.md index 5b7cb2222bf..1ab9b53db13 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ OpenAPI Generator allows generation of API client libraries (SDK generation), se | | Languages/Frameworks | |-|-| **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.0, .NET Core 2.0), **C++** (cpp-restsdk, Qt5, Tizen), **Clojure**, **Dart (1.x, 2.x)**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured, Spring 5 Web Client), **Kotlin**, **Lua**, **Nim**, **Node.js/JavaScript** (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types), **Objective-C**, **OCaml**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (rust, rust-server), **Scala** (akka, http4s, scalaz, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x), **Typescript** (AngularJS, Angular (2.x - 8.x), Aurelia, Axios, Fetch, Inversify, jQuery, Node, Rxjs) -**Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin), **Haskell** (Servant), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, Jersey, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples)), **Kotlin** (Spring Boot, Ktor), **PHP** (Laravel, Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (rust-server), **Scala** ([Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra) +**Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin), **Haskell** (Servant), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, Jersey, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples)), **Kotlin** (Spring Boot, Ktor, Vertx), **PHP** (Laravel, Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (rust-server), **Scala** ([Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra) **API documentation generators** | **HTML**, **Confluence Wiki**, **Asciidoc** **Configuration files** | [**Apache2**](https://httpd.apache.org/) **Others** | **GraphQL**, **JMeter**, **MySQL Schema**, **Protocol Buffer** @@ -748,6 +748,7 @@ Here is a list of template creators: * JAX-RS RestEasy (JBoss EAP): @jfiala * Kotlin: @jimschubert [:heart:](https://www.patreon.com/jimschubert) * Kotlin (Spring Boot): @dr4ke616 + * Kotlin (Vertx): @Wooyme * NodeJS Express: @YishTish * PHP Laravel: @renepardon * PHP Lumen: @abcsun diff --git a/docs/generators.md b/docs/generators.md index 1a4cf2c2892..7cdf880edd7 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -95,7 +95,7 @@ The following generators are available: * [jaxrs-spec](generators/jaxrs-spec) * [kotlin-server](generators/kotlin-server) * [kotlin-spring](generators/kotlin-spring) -* [kotlin-vertx](generators/kotlin-vertx) +* [kotlin-vertx (beta)](generators/kotlin-vertx) * [nodejs-express-server (beta)](generators/nodejs-express-server) * [nodejs-server-deprecated (deprecated)](generators/nodejs-server-deprecated) * [php-laravel](generators/php-laravel) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java index 19863e9a67b..36fddf1812a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java @@ -19,6 +19,8 @@ package org.openapitools.codegen.languages; import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenType; import org.openapitools.codegen.SupportingFile; +import org.openapitools.codegen.meta.GeneratorMetadata; +import org.openapitools.codegen.meta.Stability; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,6 +53,10 @@ public class KotlinVertxServerCodegen extends AbstractKotlinCodegen { public KotlinVertxServerCodegen() { super(); + generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata) + .stability(Stability.BETA) + .build(); + outputFolder = "generated-code" + File.separator + "kotlin-vertx"; modelTemplateFiles.put("model.mustache", ".kt"); @@ -61,7 +67,7 @@ public class KotlinVertxServerCodegen extends AbstractKotlinCodegen { apiTemplateFiles.clear(); apiTemplateFiles.put("api.mustache", ".kt"); apiTemplateFiles.put("apiProxy.mustache", "VertxProxyHandler.kt"); - apiTemplateFiles.put("api_verticle.mustache","Verticle.kt"); + apiTemplateFiles.put("api_verticle.mustache", "Verticle.kt"); embeddedTemplateDir = templateDir = "kotlin-vertx-server"; apiPackage = rootPackage + ".verticle"; @@ -78,8 +84,4 @@ public class KotlinVertxServerCodegen extends AbstractKotlinCodegen { } - @Override - public String escapeReservedWord(String name) { - return name; - } } diff --git a/pom.xml b/pom.xml index a9229c74a79..74e5a30947b 100644 --- a/pom.xml +++ b/pom.xml @@ -1166,6 +1166,7 @@ samples/server/petstore/scala-play-server samples/server/petstore/scalatra samples/server/petstore/scala-finch + samples/server/petstore/kotlin/vertx samples/server/petstore/kotlin-springboot diff --git a/samples/server/petstore/kotlin/vertx/.openapi-generator-ignore b/samples/server/petstore/kotlin/vertx/.openapi-generator-ignore new file mode 100644 index 00000000000..7484ee590a3 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/.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/vertx/.openapi-generator/VERSION b/samples/server/petstore/kotlin/vertx/.openapi-generator/VERSION new file mode 100644 index 00000000000..0e97bd19efb --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/.openapi-generator/VERSION @@ -0,0 +1 @@ +4.1.3-SNAPSHOT \ No newline at end of file diff --git a/samples/server/petstore/kotlin/vertx/README.md b/samples/server/petstore/kotlin/vertx/README.md new file mode 100644 index 00000000000..4e9992d66cb --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/README.md @@ -0,0 +1,81 @@ +# org.openapitools - Kotlin Server library for OpenAPI Petstore + +## Requires + +* Kotlin 1.3.10 +* Maven 3.3 + +## Build + +``` +mvn clean package +``` + +This runs all tests and packages the library. + +## Features/Implementation Notes + +* Supports JSON inputs/outputs and Form inputs. +* Supports collection formats for query parameters: csv, tsv, ssv, pipes. +* Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions. + + + ## Documentation for API Endpoints + + All URIs are relative to *http://petstore.swagger.io/v2* + + Class | Method | HTTP request | Description + ------------ | ------------- | ------------- | ------------- + *PetApi* | [**addPet**](docs/PetApi.md#addpet) | **POST** /pet | Add a new pet to the store + *PetApi* | [**deletePet**](docs/PetApi.md#deletepet) | **DELETE** /pet/{petId} | Deletes a pet + *PetApi* | [**findPetsByStatus**](docs/PetApi.md#findpetsbystatus) | **GET** /pet/findByStatus | Finds Pets by status + *PetApi* | [**findPetsByTags**](docs/PetApi.md#findpetsbytags) | **GET** /pet/findByTags | Finds Pets by tags + *PetApi* | [**getPetById**](docs/PetApi.md#getpetbyid) | **GET** /pet/{petId} | Find pet by ID + *PetApi* | [**updatePet**](docs/PetApi.md#updatepet) | **PUT** /pet | Update an existing pet + *PetApi* | [**updatePetWithForm**](docs/PetApi.md#updatepetwithform) | **POST** /pet/{petId} | Updates a pet in the store with form data + *PetApi* | [**uploadFile**](docs/PetApi.md#uploadfile) | **POST** /pet/{petId}/uploadImage | uploads an image + *StoreApi* | [**deleteOrder**](docs/StoreApi.md#deleteorder) | **DELETE** /store/order/{orderId} | Delete purchase order by ID + *StoreApi* | [**getInventory**](docs/StoreApi.md#getinventory) | **GET** /store/inventory | Returns pet inventories by status + *StoreApi* | [**getOrderById**](docs/StoreApi.md#getorderbyid) | **GET** /store/order/{orderId} | Find purchase order by ID + *StoreApi* | [**placeOrder**](docs/StoreApi.md#placeorder) | **POST** /store/order | Place an order for a pet + *UserApi* | [**createUser**](docs/UserApi.md#createuser) | **POST** /user | Create user + *UserApi* | [**createUsersWithArrayInput**](docs/UserApi.md#createuserswitharrayinput) | **POST** /user/createWithArray | Creates list of users with given input array + *UserApi* | [**createUsersWithListInput**](docs/UserApi.md#createuserswithlistinput) | **POST** /user/createWithList | Creates list of users with given input array + *UserApi* | [**deleteUser**](docs/UserApi.md#deleteuser) | **DELETE** /user/{username} | Delete user + *UserApi* | [**getUserByName**](docs/UserApi.md#getuserbyname) | **GET** /user/{username} | Get user by user name + *UserApi* | [**loginUser**](docs/UserApi.md#loginuser) | **GET** /user/login | Logs user into the system + *UserApi* | [**logoutUser**](docs/UserApi.md#logoutuser) | **GET** /user/logout | Logs out current logged in user session + *UserApi* | [**updateUser**](docs/UserApi.md#updateuser) | **PUT** /user/{username} | Updated user + + + + ## Documentation for Models + + - [org.openapitools.server.api.model.ApiResponse](docs/ApiResponse.md) + - [org.openapitools.server.api.model.Category](docs/Category.md) + - [org.openapitools.server.api.model.Order](docs/Order.md) + - [org.openapitools.server.api.model.Pet](docs/Pet.md) + - [org.openapitools.server.api.model.Tag](docs/Tag.md) + - [org.openapitools.server.api.model.User](docs/User.md) + + + +## Documentation for Authorization + + + ### api_key + + - **Type**: API key + - **API key parameter name**: api_key + - **Location**: HTTP header + + + ### petstore_auth + + - **Type**: OAuth + - **Flow**: implicit + - **Authorization URL**: http://petstore.swagger.io/api/oauth/dialog + - **Scopes**: + - write:pets: modify pets in your account + - read:pets: read your pets + diff --git a/samples/server/petstore/kotlin/vertx/pom.xml b/samples/server/petstore/kotlin/vertx/pom.xml new file mode 100644 index 00000000000..c6be42bad59 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/pom.xml @@ -0,0 +1,190 @@ + + 4.0.0 + + org.openapitools + openapi-kotlin-vertx-server + 1.0.0-SNAPSHOT + jar + + OpenAPI Petstore + + + UTF-8 + 1.8 + 1.3.10 + true + 4.12 + 3.4.1 + 3.3 + 1.0.2 + 2.3 + 2.7.4 + 3.6.0 + + + + + junit + junit + ${junit.version} + test + + + + io.vertx + vertx-unit + ${vertx.version} + test + + + + com.github.wooyme + vertx-openapi-router + ${vertx-openapi-router.version} + + + + com.google.code.gson + gson + 2.8.5 + + + + javax.annotation + javax.annotation-api + 1.2 + + + org.jetbrains.kotlin + kotlin-stdlib + ${kotlin.version} + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + RELEASE + + + + io.vertx + vertx-core + ${vertx.version} + + + io.vertx + vertx-web + ${vertx.version} + + + + io.vertx + vertx-lang-kotlin + ${vertx.version} + + + + io.vertx + vertx-lang-kotlin-coroutines + ${vertx.version} + + + + io.swagger.parser.v3 + swagger-parser + 2.0.5 + + + + io.vertx + vertx-web-api-contract + ${vertx.version} + + + + io.vertx + vertx-service-proxy + ${vertx.version} + + + + io.vertx + vertx-web-api-service + ${vertx.version} + + + + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + compile + + compile + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/main/java + + 1.8 + + + + test-compile + + test-compile + + + + ${project.basedir}/src/test/kotlin + ${project.basedir}/src/test/java + + 1.8 + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + ${maven-shade-plugin.version} + + + package + + shade + + + + + + org.openapitools.server.api.verticle.DefaultApiVerticleKt + + + + + ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar + + + + + + + \ No newline at end of file diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/ApiResponse.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/ApiResponse.kt new file mode 100644 index 00000000000..223e80919ac --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/ApiResponse.kt @@ -0,0 +1,34 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +package org.openapitools.server.api.model + + + +import com.google.gson.annotations.SerializedName +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude +/** + * Describes the result of uploading an image resource + * @param code + * @param type + * @param message + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +data class ApiResponse ( + var code: kotlin.Int? = null, + var type: kotlin.String? = null, + var message: kotlin.String? = null +) { + +} + diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Category.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Category.kt new file mode 100644 index 00000000000..29aaa19c2c2 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Category.kt @@ -0,0 +1,32 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +package org.openapitools.server.api.model + + + +import com.google.gson.annotations.SerializedName +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude +/** + * A category for a pet + * @param id + * @param name + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +data class Category ( + var id: kotlin.Long? = null, + var name: kotlin.String? = null +) { + +} + diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Order.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Order.kt new file mode 100644 index 00000000000..2d806e9e2fc --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Order.kt @@ -0,0 +1,55 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +package org.openapitools.server.api.model + + + +import com.google.gson.annotations.SerializedName +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude +/** + * An order for a pets from the pet store + * @param id + * @param petId + * @param quantity + * @param shipDate + * @param status Order Status + * @param complete + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +data class Order ( + var id: kotlin.Long? = null, + var petId: kotlin.Long? = null, + var quantity: kotlin.Int? = null, + var shipDate: java.time.LocalDateTime? = null, + /* Order Status */ + var status: Order.Status? = null, + var complete: kotlin.Boolean? = null +) { + + /** + * Order Status + * Values: placed,approved,delivered + */ + enum class Status(val value: kotlin.String){ + + placed("placed"), + + approved("approved"), + + delivered("delivered"); + + } + +} + diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Pet.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Pet.kt new file mode 100644 index 00000000000..b96a3dde895 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Pet.kt @@ -0,0 +1,61 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +package org.openapitools.server.api.model + +import org.openapitools.server.api.model.Category +import org.openapitools.server.api.model.Tag + + +import com.google.gson.annotations.SerializedName +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude +/** + * A pet for sale in the pet store + * @param id + * @param category + * @param name + * @param photoUrls + * @param tags + * @param status pet status in the store + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +data class Pet ( + @SerializedName("name") private var _name: kotlin.String?, + @SerializedName("photoUrls") private var _photoUrls: kotlin.Array?, + var id: kotlin.Long? = null, + var category: Category? = null, + var tags: kotlin.Array? = null, + /* pet status in the store */ + var status: Pet.Status? = null +) { + + /** + * pet status in the store + * Values: available,pending,sold + */ + enum class Status(val value: kotlin.String){ + + available("available"), + + pending("pending"), + + sold("sold"); + + } + + var name get() = _name ?: throw IllegalArgumentException("name is required") + set(value){ _name = value } + var photoUrls get() = _photoUrls ?: throw IllegalArgumentException("photoUrls is required") + set(value){ _photoUrls = value } +} + diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Tag.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Tag.kt new file mode 100644 index 00000000000..359a53af609 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/Tag.kt @@ -0,0 +1,32 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +package org.openapitools.server.api.model + + + +import com.google.gson.annotations.SerializedName +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude +/** + * A tag for a pet + * @param id + * @param name + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +data class Tag ( + var id: kotlin.Long? = null, + var name: kotlin.String? = null +) { + +} + diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/User.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/User.kt new file mode 100644 index 00000000000..791d0b88233 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/User.kt @@ -0,0 +1,45 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +package org.openapitools.server.api.model + + + +import com.google.gson.annotations.SerializedName +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude +/** + * 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 + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +data class User ( + var id: kotlin.Long? = null, + var username: kotlin.String? = null, + var firstName: kotlin.String? = null, + var lastName: kotlin.String? = null, + var email: kotlin.String? = null, + var password: kotlin.String? = null, + var phone: kotlin.String? = null, + /* User Status */ + var userStatus: kotlin.Int? = null +) { + +} + diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApi.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApi.kt new file mode 100644 index 00000000000..07f92471774 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApi.kt @@ -0,0 +1,70 @@ +package org.openapitools.server.api.verticle + +import org.openapitools.server.api.model.ApiResponse +import org.openapitools.server.api.model.Pet +import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject +import io.vertx.core.json.JsonArray +import com.github.wooyme.openapi.Response +import io.vertx.ext.web.api.OperationRequest +import io.vertx.kotlin.ext.web.api.contract.openapi3.OpenAPI3RouterFactory +import io.vertx.serviceproxy.ServiceBinder +import io.vertx.ext.web.handler.CookieHandler +import io.vertx.ext.web.handler.SessionHandler +import io.vertx.ext.web.sstore.LocalSessionStore +import java.util.List +import java.util.Map + + +interface PetApi { + fun init(vertx:Vertx,config:JsonObject) + /* addPet + * Add a new pet to the store */ + suspend fun addPet(body:Pet?,context:OperationRequest):Response + /* deletePet + * Deletes a pet */ + suspend fun deletePet(petId:kotlin.Long?,apiKey:kotlin.String?,context:OperationRequest):Response + /* findPetsByStatus + * Finds Pets by status */ + suspend fun findPetsByStatus(status:kotlin.Array?,context:OperationRequest):Response> + /* findPetsByTags + * Finds Pets by tags */ + suspend fun findPetsByTags(tags:kotlin.Array?,context:OperationRequest):Response> + /* getPetById + * Find pet by ID */ + suspend fun getPetById(petId:kotlin.Long?,context:OperationRequest):Response + /* updatePet + * Update an existing pet */ + suspend fun updatePet(body:Pet?,context:OperationRequest):Response + /* updatePetWithForm + * Updates a pet in the store with form data */ + suspend fun updatePetWithForm(petId:kotlin.Long?,name:kotlin.String?,status:kotlin.String?,context:OperationRequest):Response + /* uploadFile + * uploads an image */ + suspend fun uploadFile(petId:kotlin.Long?,additionalMetadata:kotlin.String?,file:kotlin.collections.List?,context:OperationRequest):Response + companion object { + const val address = "PetApi-service" + suspend fun createRouterFactory(vertx: Vertx,path:String): io.vertx.ext.web.api.contract.openapi3.OpenAPI3RouterFactory { + val routerFactory = OpenAPI3RouterFactory.createAwait(vertx,path) + routerFactory.addGlobalHandler(CookieHandler.create()) + routerFactory.addGlobalHandler(SessionHandler.create(LocalSessionStore.create(vertx))) + routerFactory.setExtraOperationContextPayloadMapper{ + JsonObject().put("files",JsonArray(it.fileUploads().map { it.uploadedFileName() })) + } + val opf = routerFactory::class.java.getDeclaredField("operations") + opf.isAccessible = true + val operations = opf.get(routerFactory) as Map + for (m in PetApi::class.java.methods) { + val methodName = m.name + val op = operations[methodName] + if (op != null) { + val method = op::class.java.getDeclaredMethod("mountRouteToService",String::class.java,String::class.java) + method.isAccessible = true + method.invoke(op,address,methodName) + } + } + routerFactory.mountServiceInterface(PetApi::class.java, address) + return routerFactory + } + } +} diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVerticle.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVerticle.kt new file mode 100644 index 00000000000..ea5e7b5f4f1 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVerticle.kt @@ -0,0 +1,19 @@ +package org.openapitools.server.api.verticle +import io.vertx.core.Vertx +import io.vertx.core.AbstractVerticle +import io.vertx.serviceproxy.ServiceBinder + +fun main(){ + Vertx.vertx().deployVerticle(PetApiVerticle()) +} + +class PetApiVerticle:AbstractVerticle() { + + override fun start() { + val instance = (javaClass.classLoader.loadClass("org.openapitools.server.api.verticle.PetApiImpl").newInstance() as PetApi) + instance.init(vertx,config()) + ServiceBinder(vertx) + .setAddress(PetApi.address) + .register(PetApi::class.java,instance) + } +} \ No newline at end of file diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVertxProxyHandler.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVertxProxyHandler.kt new file mode 100644 index 00000000000..6d4fcafa98b --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVertxProxyHandler.kt @@ -0,0 +1,214 @@ +package org.openapitools.server.api.verticle + +import io.vertx.core.Vertx +import io.vertx.core.eventbus.Message +import io.vertx.core.json.JsonObject +import io.vertx.ext.web.api.OperationRequest +import io.vertx.ext.web.api.OperationResponse +import io.vertx.ext.web.api.generator.ApiHandlerUtils +import io.vertx.serviceproxy.ProxyHandler +import io.vertx.serviceproxy.ServiceException +import io.vertx.serviceproxy.ServiceExceptionMessageCodec +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import io.vertx.kotlin.coroutines.dispatcher +import io.vertx.core.json.Json +import io.vertx.core.json.JsonArray +import com.google.gson.reflect.TypeToken +import com.google.gson.Gson +import org.openapitools.server.api.model.ApiResponse +import org.openapitools.server.api.model.Pet + +class PetApiVertxProxyHandler(private val vertx: Vertx, private val service: PetApi, topLevel: Boolean, private val timeoutSeconds: Long) : ProxyHandler() { + private val timerID: Long + private var lastAccessed: Long = 0 + init { + try { + this.vertx.eventBus().registerDefaultCodec(ServiceException::class.java, + ServiceExceptionMessageCodec()) + } catch (ex: IllegalStateException) {} + + if (timeoutSeconds != (-1).toLong() && !topLevel) { + var period = timeoutSeconds * 1000 / 2 + if (period > 10000) { + period = 10000 + } + this.timerID = vertx.setPeriodic(period) { this.checkTimedOut(it) } + } else { + this.timerID = -1 + } + accessed() + } + private fun checkTimedOut(id: Long) { + val now = System.nanoTime() + if (now - lastAccessed > timeoutSeconds * 1000000000) { + close() + } + } + + override fun close() { + if (timerID != (-1).toLong()) { + vertx.cancelTimer(timerID) + } + super.close() + } + + private fun accessed() { + this.lastAccessed = System.nanoTime() + } + override fun handle(msg: Message) { + try { + val json = msg.body() + val action = msg.headers().get("action") ?: throw IllegalStateException("action not specified") + accessed() + val contextSerialized = json.getJsonObject("context") ?: throw IllegalStateException("Received action $action without OperationRequest \"context\"") + val context = OperationRequest(contextSerialized) + when (action) { + + "addPet" -> { + val params = context.params + val bodyParam = ApiHandlerUtils.searchJsonObjectInJson(params,"body") + if (bodyParam == null) { + throw IllegalArgumentException("body is required") + } + val body = Gson().fromJson(bodyParam.encode(), Pet::class.java) + GlobalScope.launch(vertx.dispatcher()){ + val result = service.addPet(body,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "deletePet" -> { + val params = context.params + val petId = ApiHandlerUtils.searchLongInJson(params,"petId") + if(petId == null){ + throw IllegalArgumentException("petId is required") + } + val apiKey = ApiHandlerUtils.searchStringInJson(params,"api_key") + GlobalScope.launch(vertx.dispatcher()){ + val result = service.deletePet(petId,apiKey,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "findPetsByStatus" -> { + val params = context.params + val statusParam = ApiHandlerUtils.searchJsonArrayInJson(params,"status") + if(statusParam == null){ + throw IllegalArgumentException("status is required") + } + val status:kotlin.Array = Gson().fromJson(statusParam.encode() + , object : TypeToken>(){}.type) + GlobalScope.launch(vertx.dispatcher()){ + val result = service.findPetsByStatus(status,context) + val payload = JsonArray(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "findPetsByTags" -> { + val params = context.params + val tagsParam = ApiHandlerUtils.searchJsonArrayInJson(params,"tags") + if(tagsParam == null){ + throw IllegalArgumentException("tags is required") + } + val tags:kotlin.Array = Gson().fromJson(tagsParam.encode() + , object : TypeToken>(){}.type) + GlobalScope.launch(vertx.dispatcher()){ + val result = service.findPetsByTags(tags,context) + val payload = JsonArray(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "getPetById" -> { + val params = context.params + val petId = ApiHandlerUtils.searchLongInJson(params,"petId") + if(petId == null){ + throw IllegalArgumentException("petId is required") + } + GlobalScope.launch(vertx.dispatcher()){ + val result = service.getPetById(petId,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "updatePet" -> { + val params = context.params + val bodyParam = ApiHandlerUtils.searchJsonObjectInJson(params,"body") + if (bodyParam == null) { + throw IllegalArgumentException("body is required") + } + val body = Gson().fromJson(bodyParam.encode(), Pet::class.java) + GlobalScope.launch(vertx.dispatcher()){ + val result = service.updatePet(body,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "updatePetWithForm" -> { + val params = context.params + val petId = ApiHandlerUtils.searchLongInJson(params,"petId") + if(petId == null){ + throw IllegalArgumentException("petId is required") + } + val name = ApiHandlerUtils.searchStringInJson(params,"name") + val status = ApiHandlerUtils.searchStringInJson(params,"status") + GlobalScope.launch(vertx.dispatcher()){ + val result = service.updatePetWithForm(petId,name,status,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "uploadFile" -> { + val params = context.params + val petId = ApiHandlerUtils.searchLongInJson(params,"petId") + if(petId == null){ + throw IllegalArgumentException("petId is required") + } + val additionalMetadata = ApiHandlerUtils.searchStringInJson(params,"additionalMetadata") + val fileParam = context.extra.getJsonArray("files") + val file = fileParam?.map{ java.io.File(it as String) } + GlobalScope.launch(vertx.dispatcher()){ + val result = service.uploadFile(petId,additionalMetadata,file,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + } + }catch (t: Throwable) { + msg.reply(ServiceException(500, t.message)) + throw t + } + } +} diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApi.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApi.kt new file mode 100644 index 00000000000..ac40c5a4527 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApi.kt @@ -0,0 +1,57 @@ +package org.openapitools.server.api.verticle + +import org.openapitools.server.api.model.Order +import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject +import io.vertx.core.json.JsonArray +import com.github.wooyme.openapi.Response +import io.vertx.ext.web.api.OperationRequest +import io.vertx.kotlin.ext.web.api.contract.openapi3.OpenAPI3RouterFactory +import io.vertx.serviceproxy.ServiceBinder +import io.vertx.ext.web.handler.CookieHandler +import io.vertx.ext.web.handler.SessionHandler +import io.vertx.ext.web.sstore.LocalSessionStore +import java.util.List +import java.util.Map + + +interface StoreApi { + fun init(vertx:Vertx,config:JsonObject) + /* deleteOrder + * Delete purchase order by ID */ + suspend fun deleteOrder(orderId:kotlin.String?,context:OperationRequest):Response + /* getInventory + * Returns pet inventories by status */ + suspend fun getInventory(context:OperationRequest):Response> + /* getOrderById + * Find purchase order by ID */ + suspend fun getOrderById(orderId:kotlin.Long?,context:OperationRequest):Response + /* placeOrder + * Place an order for a pet */ + suspend fun placeOrder(body:Order?,context:OperationRequest):Response + companion object { + const val address = "StoreApi-service" + suspend fun createRouterFactory(vertx: Vertx,path:String): io.vertx.ext.web.api.contract.openapi3.OpenAPI3RouterFactory { + val routerFactory = OpenAPI3RouterFactory.createAwait(vertx,path) + routerFactory.addGlobalHandler(CookieHandler.create()) + routerFactory.addGlobalHandler(SessionHandler.create(LocalSessionStore.create(vertx))) + routerFactory.setExtraOperationContextPayloadMapper{ + JsonObject().put("files",JsonArray(it.fileUploads().map { it.uploadedFileName() })) + } + val opf = routerFactory::class.java.getDeclaredField("operations") + opf.isAccessible = true + val operations = opf.get(routerFactory) as Map + for (m in StoreApi::class.java.methods) { + val methodName = m.name + val op = operations[methodName] + if (op != null) { + val method = op::class.java.getDeclaredMethod("mountRouteToService",String::class.java,String::class.java) + method.isAccessible = true + method.invoke(op,address,methodName) + } + } + routerFactory.mountServiceInterface(StoreApi::class.java, address) + return routerFactory + } + } +} diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApiVerticle.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApiVerticle.kt new file mode 100644 index 00000000000..dd885532237 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApiVerticle.kt @@ -0,0 +1,19 @@ +package org.openapitools.server.api.verticle +import io.vertx.core.Vertx +import io.vertx.core.AbstractVerticle +import io.vertx.serviceproxy.ServiceBinder + +fun main(){ + Vertx.vertx().deployVerticle(StoreApiVerticle()) +} + +class StoreApiVerticle:AbstractVerticle() { + + override fun start() { + val instance = (javaClass.classLoader.loadClass("org.openapitools.server.api.verticle.StoreApiImpl").newInstance() as StoreApi) + instance.init(vertx,config()) + ServiceBinder(vertx) + .setAddress(StoreApi.address) + .register(StoreApi::class.java,instance) + } +} \ No newline at end of file diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApiVertxProxyHandler.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApiVertxProxyHandler.kt new file mode 100644 index 00000000000..985b9249f56 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/StoreApiVertxProxyHandler.kt @@ -0,0 +1,125 @@ +package org.openapitools.server.api.verticle + +import io.vertx.core.Vertx +import io.vertx.core.eventbus.Message +import io.vertx.core.json.JsonObject +import io.vertx.ext.web.api.OperationRequest +import io.vertx.ext.web.api.OperationResponse +import io.vertx.ext.web.api.generator.ApiHandlerUtils +import io.vertx.serviceproxy.ProxyHandler +import io.vertx.serviceproxy.ServiceException +import io.vertx.serviceproxy.ServiceExceptionMessageCodec +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import io.vertx.kotlin.coroutines.dispatcher +import io.vertx.core.json.Json +import io.vertx.core.json.JsonArray +import com.google.gson.reflect.TypeToken +import com.google.gson.Gson +import org.openapitools.server.api.model.Order + +class StoreApiVertxProxyHandler(private val vertx: Vertx, private val service: StoreApi, topLevel: Boolean, private val timeoutSeconds: Long) : ProxyHandler() { + private val timerID: Long + private var lastAccessed: Long = 0 + init { + try { + this.vertx.eventBus().registerDefaultCodec(ServiceException::class.java, + ServiceExceptionMessageCodec()) + } catch (ex: IllegalStateException) {} + + if (timeoutSeconds != (-1).toLong() && !topLevel) { + var period = timeoutSeconds * 1000 / 2 + if (period > 10000) { + period = 10000 + } + this.timerID = vertx.setPeriodic(period) { this.checkTimedOut(it) } + } else { + this.timerID = -1 + } + accessed() + } + private fun checkTimedOut(id: Long) { + val now = System.nanoTime() + if (now - lastAccessed > timeoutSeconds * 1000000000) { + close() + } + } + + override fun close() { + if (timerID != (-1).toLong()) { + vertx.cancelTimer(timerID) + } + super.close() + } + + private fun accessed() { + this.lastAccessed = System.nanoTime() + } + override fun handle(msg: Message) { + try { + val json = msg.body() + val action = msg.headers().get("action") ?: throw IllegalStateException("action not specified") + accessed() + val contextSerialized = json.getJsonObject("context") ?: throw IllegalStateException("Received action $action without OperationRequest \"context\"") + val context = OperationRequest(contextSerialized) + when (action) { + + "deleteOrder" -> { + val params = context.params + val orderId = ApiHandlerUtils.searchStringInJson(params,"orderId") + if(orderId == null){ + throw IllegalArgumentException("orderId is required") + } + GlobalScope.launch(vertx.dispatcher()){ + val result = service.deleteOrder(orderId,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "getInventory" -> { + } + + "getOrderById" -> { + val params = context.params + val orderId = ApiHandlerUtils.searchLongInJson(params,"orderId") + if(orderId == null){ + throw IllegalArgumentException("orderId is required") + } + GlobalScope.launch(vertx.dispatcher()){ + val result = service.getOrderById(orderId,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "placeOrder" -> { + val params = context.params + val bodyParam = ApiHandlerUtils.searchJsonObjectInJson(params,"body") + if (bodyParam == null) { + throw IllegalArgumentException("body is required") + } + val body = Gson().fromJson(bodyParam.encode(), Order::class.java) + GlobalScope.launch(vertx.dispatcher()){ + val result = service.placeOrder(body,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + } + }catch (t: Throwable) { + msg.reply(ServiceException(500, t.message)) + throw t + } + } +} diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApi.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApi.kt new file mode 100644 index 00000000000..e48a7273b2a --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApi.kt @@ -0,0 +1,69 @@ +package org.openapitools.server.api.verticle + +import org.openapitools.server.api.model.User +import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject +import io.vertx.core.json.JsonArray +import com.github.wooyme.openapi.Response +import io.vertx.ext.web.api.OperationRequest +import io.vertx.kotlin.ext.web.api.contract.openapi3.OpenAPI3RouterFactory +import io.vertx.serviceproxy.ServiceBinder +import io.vertx.ext.web.handler.CookieHandler +import io.vertx.ext.web.handler.SessionHandler +import io.vertx.ext.web.sstore.LocalSessionStore +import java.util.List +import java.util.Map + + +interface UserApi { + fun init(vertx:Vertx,config:JsonObject) + /* createUser + * Create user */ + suspend fun createUser(body:User?,context:OperationRequest):Response + /* createUsersWithArrayInput + * Creates list of users with given input array */ + suspend fun createUsersWithArrayInput(body:kotlin.Array?,context:OperationRequest):Response + /* createUsersWithListInput + * Creates list of users with given input array */ + suspend fun createUsersWithListInput(body:kotlin.Array?,context:OperationRequest):Response + /* deleteUser + * Delete user */ + suspend fun deleteUser(username:kotlin.String?,context:OperationRequest):Response + /* getUserByName + * Get user by user name */ + suspend fun getUserByName(username:kotlin.String?,context:OperationRequest):Response + /* loginUser + * Logs user into the system */ + suspend fun loginUser(username:kotlin.String?,password:kotlin.String?,context:OperationRequest):Response + /* logoutUser + * Logs out current logged in user session */ + suspend fun logoutUser(context:OperationRequest):Response + /* updateUser + * Updated user */ + suspend fun updateUser(username:kotlin.String?,body:User?,context:OperationRequest):Response + companion object { + const val address = "UserApi-service" + suspend fun createRouterFactory(vertx: Vertx,path:String): io.vertx.ext.web.api.contract.openapi3.OpenAPI3RouterFactory { + val routerFactory = OpenAPI3RouterFactory.createAwait(vertx,path) + routerFactory.addGlobalHandler(CookieHandler.create()) + routerFactory.addGlobalHandler(SessionHandler.create(LocalSessionStore.create(vertx))) + routerFactory.setExtraOperationContextPayloadMapper{ + JsonObject().put("files",JsonArray(it.fileUploads().map { it.uploadedFileName() })) + } + val opf = routerFactory::class.java.getDeclaredField("operations") + opf.isAccessible = true + val operations = opf.get(routerFactory) as Map + for (m in UserApi::class.java.methods) { + val methodName = m.name + val op = operations[methodName] + if (op != null) { + val method = op::class.java.getDeclaredMethod("mountRouteToService",String::class.java,String::class.java) + method.isAccessible = true + method.invoke(op,address,methodName) + } + } + routerFactory.mountServiceInterface(UserApi::class.java, address) + return routerFactory + } + } +} diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApiVerticle.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApiVerticle.kt new file mode 100644 index 00000000000..2b121c28bb1 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApiVerticle.kt @@ -0,0 +1,19 @@ +package org.openapitools.server.api.verticle +import io.vertx.core.Vertx +import io.vertx.core.AbstractVerticle +import io.vertx.serviceproxy.ServiceBinder + +fun main(){ + Vertx.vertx().deployVerticle(UserApiVerticle()) +} + +class UserApiVerticle:AbstractVerticle() { + + override fun start() { + val instance = (javaClass.classLoader.loadClass("org.openapitools.server.api.verticle.UserApiImpl").newInstance() as UserApi) + instance.init(vertx,config()) + ServiceBinder(vertx) + .setAddress(UserApi.address) + .register(UserApi::class.java,instance) + } +} \ No newline at end of file diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApiVertxProxyHandler.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApiVertxProxyHandler.kt new file mode 100644 index 00000000000..beee4405bee --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/UserApiVertxProxyHandler.kt @@ -0,0 +1,202 @@ +package org.openapitools.server.api.verticle + +import io.vertx.core.Vertx +import io.vertx.core.eventbus.Message +import io.vertx.core.json.JsonObject +import io.vertx.ext.web.api.OperationRequest +import io.vertx.ext.web.api.OperationResponse +import io.vertx.ext.web.api.generator.ApiHandlerUtils +import io.vertx.serviceproxy.ProxyHandler +import io.vertx.serviceproxy.ServiceException +import io.vertx.serviceproxy.ServiceExceptionMessageCodec +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import io.vertx.kotlin.coroutines.dispatcher +import io.vertx.core.json.Json +import io.vertx.core.json.JsonArray +import com.google.gson.reflect.TypeToken +import com.google.gson.Gson +import org.openapitools.server.api.model.User + +class UserApiVertxProxyHandler(private val vertx: Vertx, private val service: UserApi, topLevel: Boolean, private val timeoutSeconds: Long) : ProxyHandler() { + private val timerID: Long + private var lastAccessed: Long = 0 + init { + try { + this.vertx.eventBus().registerDefaultCodec(ServiceException::class.java, + ServiceExceptionMessageCodec()) + } catch (ex: IllegalStateException) {} + + if (timeoutSeconds != (-1).toLong() && !topLevel) { + var period = timeoutSeconds * 1000 / 2 + if (period > 10000) { + period = 10000 + } + this.timerID = vertx.setPeriodic(period) { this.checkTimedOut(it) } + } else { + this.timerID = -1 + } + accessed() + } + private fun checkTimedOut(id: Long) { + val now = System.nanoTime() + if (now - lastAccessed > timeoutSeconds * 1000000000) { + close() + } + } + + override fun close() { + if (timerID != (-1).toLong()) { + vertx.cancelTimer(timerID) + } + super.close() + } + + private fun accessed() { + this.lastAccessed = System.nanoTime() + } + override fun handle(msg: Message) { + try { + val json = msg.body() + val action = msg.headers().get("action") ?: throw IllegalStateException("action not specified") + accessed() + val contextSerialized = json.getJsonObject("context") ?: throw IllegalStateException("Received action $action without OperationRequest \"context\"") + val context = OperationRequest(contextSerialized) + when (action) { + + "createUser" -> { + val params = context.params + val bodyParam = ApiHandlerUtils.searchJsonObjectInJson(params,"body") + if (bodyParam == null) { + throw IllegalArgumentException("body is required") + } + val body = Gson().fromJson(bodyParam.encode(), User::class.java) + GlobalScope.launch(vertx.dispatcher()){ + val result = service.createUser(body,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "createUsersWithArrayInput" -> { + val params = context.params + val bodyParam = ApiHandlerUtils.searchJsonArrayInJson(params,"body") + if(bodyParam == null){ + throw IllegalArgumentException("body is required") + } + val body:kotlin.Array = Gson().fromJson(bodyParam.encode() + , object : TypeToken>(){}.type) + GlobalScope.launch(vertx.dispatcher()){ + val result = service.createUsersWithArrayInput(body,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "createUsersWithListInput" -> { + val params = context.params + val bodyParam = ApiHandlerUtils.searchJsonArrayInJson(params,"body") + if(bodyParam == null){ + throw IllegalArgumentException("body is required") + } + val body:kotlin.Array = Gson().fromJson(bodyParam.encode() + , object : TypeToken>(){}.type) + GlobalScope.launch(vertx.dispatcher()){ + val result = service.createUsersWithListInput(body,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "deleteUser" -> { + val params = context.params + val username = ApiHandlerUtils.searchStringInJson(params,"username") + if(username == null){ + throw IllegalArgumentException("username is required") + } + GlobalScope.launch(vertx.dispatcher()){ + val result = service.deleteUser(username,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "getUserByName" -> { + val params = context.params + val username = ApiHandlerUtils.searchStringInJson(params,"username") + if(username == null){ + throw IllegalArgumentException("username is required") + } + GlobalScope.launch(vertx.dispatcher()){ + val result = service.getUserByName(username,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "loginUser" -> { + val params = context.params + val username = ApiHandlerUtils.searchStringInJson(params,"username") + if(username == null){ + throw IllegalArgumentException("username is required") + } + val password = ApiHandlerUtils.searchStringInJson(params,"password") + if(password == null){ + throw IllegalArgumentException("password is required") + } + GlobalScope.launch(vertx.dispatcher()){ + val result = service.loginUser(username,password,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + "logoutUser" -> { + } + + "updateUser" -> { + val params = context.params + val username = ApiHandlerUtils.searchStringInJson(params,"username") + if(username == null){ + throw IllegalArgumentException("username is required") + } + val bodyParam = ApiHandlerUtils.searchJsonObjectInJson(params,"body") + if (bodyParam == null) { + throw IllegalArgumentException("body is required") + } + val body = Gson().fromJson(bodyParam.encode(), User::class.java) + GlobalScope.launch(vertx.dispatcher()){ + val result = service.updateUser(username,body,context) + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + } + + } + }catch (t: Throwable) { + msg.reply(ServiceException(500, t.message)) + throw t + } + } +}