From 56798da4cfb1bf1ce5c54ad37844265cc5f005be Mon Sep 17 00:00:00 2001 From: Zheng Feng Date: Thu, 23 May 2024 16:58:47 +0800 Subject: [PATCH 1/2] Add openapi-contract-first example --- docs/modules/ROOT/attachments/examples.json | 5 + openapi-contract-first/README.adoc | 87 ++ .../eclipse-formatter-config.xml | 276 ++++ openapi-contract-first/pom.xml | 288 ++++ .../openapi/contract/first/PetStoreRoute.java | 59 + .../src/main/openapi/petstore.json | 1240 +++++++++++++++++ .../src/main/resources/application.properties | 23 + .../first/ExamplesOpenapiContractFirstIT.java | 24 + .../ExamplesOpenapiContractFirstTest.java | 38 + 9 files changed, 2040 insertions(+) create mode 100644 openapi-contract-first/README.adoc create mode 100644 openapi-contract-first/eclipse-formatter-config.xml create mode 100644 openapi-contract-first/pom.xml create mode 100644 openapi-contract-first/src/main/java/org/acme/examples/openapi/contract/first/PetStoreRoute.java create mode 100644 openapi-contract-first/src/main/openapi/petstore.json create mode 100644 openapi-contract-first/src/main/resources/application.properties create mode 100644 openapi-contract-first/src/test/java/org/acme/examples/openapi/contract/first/ExamplesOpenapiContractFirstIT.java create mode 100644 openapi-contract-first/src/test/java/org/acme/examples/openapi/contract/first/ExamplesOpenapiContractFirstTest.java diff --git a/docs/modules/ROOT/attachments/examples.json b/docs/modules/ROOT/attachments/examples.json index 436a87d2..1db0eb9d 100644 --- a/docs/modules/ROOT/attachments/examples.json +++ b/docs/modules/ROOT/attachments/examples.json @@ -79,6 +79,11 @@ "description": "Demonstrates how to add support for metrics, health checks and distributed tracing", "link": "https://github.com/apache/camel-quarkus-examples/tree/main/observability" }, + { + "title": "OpenAPI Contract First", + "description": "Shows how to run with Contract First OpenAPI.", + "link": "https://github.com/apache/camel-quarkus-examples/tree/main/openapi-contract-first" + }, { "title": "Platform HTTP security with Keycloak", "description": "Shows how to secure platform HTTP with Keycloak", diff --git a/openapi-contract-first/README.adoc b/openapi-contract-first/README.adoc new file mode 100644 index 00000000..fb3b950b --- /dev/null +++ b/openapi-contract-first/README.adoc @@ -0,0 +1,87 @@ += OpenAPI Contract First: A Camel Quarkus example +:cq-example-description: An example that shows how to run with Contract First OpenAPI. + +{cq-description} + +This example uses Camel to expose REST APIs from an existing OpenAPI specification (contract first). + +From the contract we generate Java POJO classes (using quarkus-maven-plugin, see `pom.xml`). + +In the Camel route `PetStoreRoute.java` we use Rest DSL using OpenAPI in contract-first mode. +This makes it possible to expose all the APIs very easily, and map this to corresponding Camel +routes via `direct:operationId` naming convention. + +The example uses the Petstore OpenAPI example which comes with 18 APIs. This example has only +implemented 2 of these APIs, and to ignore the remaining APIs. This is handy during development, +so you can implement the APIs one by one. + +TIP: Check the https://camel.apache.org/camel-quarkus/latest/first-steps.html[Camel Quarkus User guide] for prerequisites +and other general information. + +== Start in the Development mode + +[source,shell] +---- +$ mvn clean compile quarkus:dev +---- + +The above command compiles the project, starts the application and lets the Quarkus tooling watch for changes in your +workspace. Any modifications in your project will automatically take effect in the running application. + +TIP: Please refer to the Development mode section of +https://camel.apache.org/camel-quarkus/latest/first-steps.html#_development_mode[Camel Quarkus User guide] for more details. + +// TODO: Describe how the user should interact with the example here + +=== Package and run the application + +Once you are done with developing you may want to package and run the application. + +TIP: Find more details about the JVM mode and Native mode in the Package and run section of +https://camel.apache.org/camel-quarkus/latest/first-steps.html#_package_and_run_the_application[Camel Quarkus User guide] + +==== JVM mode + +[source,shell] +---- +$ mvn clean package +$ java -jar target/quarkus-app/quarkus-run.jar +... +[io.quarkus] (main) camel-quarkus-examples-... started in 1.163s. +---- + +==== Native mode + +IMPORTANT: Native mode requires having GraalVM and other tools installed. Please check the Prerequisites section +of https://camel.apache.org/camel-quarkus/latest/first-steps.html#_prerequisites[Camel Quarkus User guide]. + +To prepare a native executable using GraalVM, run the following command: + +[source,shell] +---- +$ mvn clean package -Pnative +$ ./target/*-runner +... +[io.quarkus] (main) camel-quarkus-examples-... started in 0.013s. +... +---- + +==== How to run + +Test the service endpoint from another terminal: + +[source,shell] +---- +curl http://localhost:8080/api/v3/pet/123 +---- + +You should get some results like: +[source] +---- +{"id":123,"name":"Tony the tiger","photoUrls":[],"status":"available"} +---- + + +== Feedback + +Please report bugs and propose improvements via https://github.com/apache/camel-quarkus/issues[GitHub issues of Camel Quarkus] project. diff --git a/openapi-contract-first/eclipse-formatter-config.xml b/openapi-contract-first/eclipse-formatter-config.xml new file mode 100644 index 00000000..2248b2b8 --- /dev/null +++ b/openapi-contract-first/eclipse-formatter-config.xml @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openapi-contract-first/pom.xml b/openapi-contract-first/pom.xml new file mode 100644 index 00000000..f8b59493 --- /dev/null +++ b/openapi-contract-first/pom.xml @@ -0,0 +1,288 @@ + + + + 4.0.0 + + camel-quarkus-examples-examples-openapi-contract-first + org.apache.camel.quarkus.examples + 3.11.0-SNAPSHOT + + Camel Quarkus :: Examples :: openapi-contract-first + Camel Quarkus Example :: openapi-contract-first + + + 3.10.0 + 3.11.0-SNAPSHOT + + io.quarkus + quarkus-bom + org.apache.camel.quarkus + camel-quarkus-bom + + UTF-8 + UTF-8 + 17 + 17 + ${maven.compiler.target} + ${maven.compiler.source} + + 2.23.0 + 1.9.0 + 4.5 + 3.13.0 + 3.4.1 + 3.3.1 + 3.2.5 + + + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + ${camel-quarkus.platform.group-id} + ${camel-quarkus.platform.artifact-id} + ${camel-quarkus.platform.version} + pom + import + + + + + + + org.apache.camel.quarkus + camel-quarkus-direct + + + org.apache.camel.quarkus + camel-quarkus-jackson + + + org.apache.camel.quarkus + camel-quarkus-rest-openapi + + + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + + src/main/openapi + + + src/main/resources + + + + + + net.revelc.code.formatter + formatter-maven-plugin + ${formatter-maven-plugin.version} + + ${maven.multiModuleProjectDirectory}/eclipse-formatter-config.xml + LF + + + + + net.revelc.code + impsort-maven-plugin + ${impsort-maven-plugin.version} + + java.,javax.,org.w3c.,org.xml.,junit. + true + true + java.,javax.,org.w3c.,org.xml.,junit. + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + true + true + + -Xlint:unchecked + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + false + + org.jboss.logmanager.LogManager + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${maven-surefire-plugin.version} + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + + com.mycila + license-maven-plugin + ${license-maven-plugin.version} + + true +
${maven.multiModuleProjectDirectory}/header.txt
+ + **/*.adoc + **/*.txt + **/LICENSE.txt + **/LICENSE + **/NOTICE.txt + **/NOTICE + **/README + **/pom.xml.versionsBackup + + + SLASHSTAR_STYLE + CAMEL_PROPERTIES_STYLE + SLASHSTAR_STYLE + + + ${maven.multiModuleProjectDirectory}/license-properties-headerdefinition.xml + +
+
+
+
+ + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + + + build + + generate-code + build + + + + + + + net.revelc.code.formatter + formatter-maven-plugin + + + format + + format + + process-sources + + + + + + net.revelc.code + impsort-maven-plugin + + + sort-imports + + sort + + process-sources + + + + +
+ + + + native + + + native + + + + native + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + ${quarkus.package.type} + + + + + + + + + + +
diff --git a/openapi-contract-first/src/main/java/org/acme/examples/openapi/contract/first/PetStoreRoute.java b/openapi-contract-first/src/main/java/org/acme/examples/openapi/contract/first/PetStoreRoute.java new file mode 100644 index 00000000..bc8270fe --- /dev/null +++ b/openapi-contract-first/src/main/java/org/acme/examples/openapi/contract/first/PetStoreRoute.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.acme.examples.openapi.contract.first; + +import jakarta.enterprise.context.ApplicationScoped; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.model.rest.RestBindingMode; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import sample.petstore.model.Pet; +import sample.petstore.model.Pet.StatusEnum; + +/** + * Camel routes for the PetStore example + */ +@ApplicationScoped +public class PetStoreRoute extends RouteBuilder { + + @ConfigProperty(name = "pet.name") + private String petName; + + @Override + public void configure() throws Exception { + // turn on json binding and scan for POJO classes in the model package + restConfiguration().bindingMode(RestBindingMode.json) + .bindingPackageScan("sample.petstore.model"); + + rest().openApi().specification("petstore.json").missingOperation("ignore"); + + from("direct:getPetById") + .process(e -> { + // build response body as POJO + Pet pet = new Pet(); + pet.setId(e.getMessage().getHeader("petId", long.class)); + pet.setName(petName); + pet.setStatus(StatusEnum.AVAILABLE); + e.getMessage().setBody(pet); + }); + + from("direct:updatePet") + .process(e -> { + Pet pet = e.getMessage().getBody(Pet.class); + pet.setStatus(StatusEnum.PENDING); + }); + } +} diff --git a/openapi-contract-first/src/main/openapi/petstore.json b/openapi-contract-first/src/main/openapi/petstore.json new file mode 100644 index 00000000..b03f0187 --- /dev/null +++ b/openapi-contract-first/src/main/openapi/petstore.json @@ -0,0 +1,1240 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "Swagger Petstore - OpenAPI 3.0", + "description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml) ", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.4" + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + }, + "servers": [ + { + "url": "{scheme}://{host}/{basePath}", + "variables": { + "scheme": { + "enum": [ + "https", + "http" + ], + "default": "https" + }, + "host": { + "default": "petstore3.swagger.io" + }, + "basePath": { + "default": "/api/v3" + } + } + } + ], + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Operations about user" + }, + { + "name": "user", + "description": "Access to Petstore orders", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + } + ], + "paths": { + "/pet": { + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "Update an existing pet by Id", + "operationId": "updatePet", + "requestBody": { + "description": "Update an existent pet in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "Add a new pet to the store", + "operationId": "addPet", + "requestBody": { + "description": "Create a new pet in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": false, + "explode": true, + "schema": { + "type": "string", + "default": "available", + "enum": [ + "available", + "pending", + "sold" + ] + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByTags": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by tags", + "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "Tags to filter by", + "required": false, + "explode": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}": { + "get": { + "tags": [ + "pet" + ], + "summary": "Find pet by ID", + "description": "Returns a single pet", + "operationId": "getPetById", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to return", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "api_key": [] + }, + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Updates a pet in the store with form data", + "description": "", + "operationId": "updatePetWithForm", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be updated", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "name", + "in": "query", + "description": "Name of pet that needs to be updated", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "description": "Status of pet that needs to be updated", + "schema": { + "type": "string" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "description": "", + "operationId": "deletePet", + "parameters": [ + { + "name": "api_key", + "in": "header", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "petId", + "in": "path", + "description": "Pet id to delete", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid pet value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}/uploadImage": { + "post": { + "tags": [ + "pet" + ], + "summary": "uploads an image", + "description": "", + "operationId": "uploadFile", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to update", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "additionalMetadata", + "in": "query", + "description": "Additional Metadata", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/store/inventory": { + "get": { + "tags": [ + "store" + ], + "summary": "Returns pet inventories by status", + "description": "Returns a map of status codes to quantities", + "operationId": "getInventory", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/store/order": { + "post": { + "tags": [ + "store" + ], + "summary": "Place an order for a pet", + "description": "Place a new order in the store", + "operationId": "placeOrder", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "405": { + "description": "Invalid input" + } + } + } + }, + "/store/order/{orderId}": { + "get": { + "tags": [ + "store" + ], + "summary": "Find purchase order by ID", + "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", + "operationId": "getOrderById", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of order that needs to be fetched", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + }, + "delete": { + "tags": [ + "store" + ], + "summary": "Delete purchase order by ID", + "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "operationId": "deleteOrder", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of the order that needs to be deleted", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + } + }, + "/user": { + "post": { + "tags": [ + "user" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "requestBody": { + "description": "Created user object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "default": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + } + }, + "/user/createWithList": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "Creates list of users with given input array", + "operationId": "createUsersWithListInput", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "default": { + "description": "successful operation" + } + } + } + }, + "/user/login": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs user into the system", + "description": "", + "operationId": "loginUser", + "parameters": [ + { + "name": "username", + "in": "query", + "description": "The user name for login", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "password", + "in": "query", + "description": "The password for login in clear text", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "headers": { + "X-Rate-Limit": { + "description": "calls per hour allowed by the user", + "schema": { + "type": "integer", + "format": "int32" + } + }, + "X-Expires-After": { + "description": "date in UTC when toekn expires", + "schema": { + "type": "string", + "format": "date-time" + } + } + }, + "content": { + "application/xml": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "Invalid username/password supplied" + } + } + } + }, + "/user/logout": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs out current logged in user session", + "description": "", + "operationId": "logoutUser", + "parameters": [], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/{username}": { + "get": { + "tags": [ + "user" + ], + "summary": "Get user by user name", + "description": "", + "operationId": "getUserByName", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be fetched. Use user1 for testing. ", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "put": { + "tags": [ + "user" + ], + "summary": "Update user", + "description": "This can only be done by the logged in user.", + "operationId": "updateUser", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "name that need to be deleted", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "Update an existent user in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "default": { + "description": "successful operation" + } + } + }, + "delete": { + "tags": [ + "user" + ], + "summary": "Delete user", + "description": "This can only be done by the logged in user.", + "operationId": "deleteUser", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be deleted", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + } + } + }, + "components": { + "schemas": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "petId": { + "type": "integer", + "format": "int64", + "example": 198772 + }, + "quantity": { + "type": "integer", + "format": "int32", + "example": 7 + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "example": "approved", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean" + } + }, + "xml": { + "name": "order" + } + }, + "Customer": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 100000 + }, + "username": { + "type": "string", + "example": "fehguy" + }, + "address": { + "type": "array", + "xml": { + "name": "addresses", + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Address" + } + } + }, + "xml": { + "name": "customer" + } + }, + "Address": { + "type": "object", + "properties": { + "street": { + "type": "string", + "example": "437 Lytton" + }, + "city": { + "type": "string", + "example": "Palo Alto" + }, + "state": { + "type": "string", + "example": "CA" + }, + "zip": { + "type": "string", + "example": "94301" + } + }, + "xml": { + "name": "address" + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "Dogs" + } + }, + "xml": { + "name": "category" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "username": { + "type": "string", + "example": "theUser" + }, + "firstName": { + "type": "string", + "example": "John" + }, + "lastName": { + "type": "string", + "example": "James" + }, + "email": { + "type": "string", + "example": "john@email.com" + }, + "password": { + "type": "string", + "example": "12345" + }, + "phone": { + "type": "string", + "example": "12345" + }, + "userStatus": { + "type": "integer", + "description": "User Status", + "format": "int32", + "example": 1 + } + }, + "xml": { + "name": "user" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "tag" + } + }, + "Pet": { + "required": [ + "name", + "photoUrls" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "doggie" + }, + "category": { + "$ref": "#/components/schemas/Category" + }, + "photoUrls": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "string", + "xml": { + "name": "photoUrl" + } + } + }, + "tags": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "pet" + } + }, + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "xml": { + "name": "##default" + } + } + }, + "requestBodies": { + "Pet": { + "description": "Pet object that needs to be added to the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "UserArray": { + "description": "List of user object", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + }, + "securitySchemes": { + "petstore_auth": { + "type": "oauth2", + "flows": { + "implicit": { + "authorizationUrl": "https://petstore3.swagger.io/oauth/authorize", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + } + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + } + } +} diff --git a/openapi-contract-first/src/main/resources/application.properties b/openapi-contract-first/src/main/resources/application.properties new file mode 100644 index 00000000..55bcfd59 --- /dev/null +++ b/openapi-contract-first/src/main/resources/application.properties @@ -0,0 +1,23 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## --------------------------------------------------------------------------- +quarkus.native.resources.includes=petstore.json +quarkus.camel.openapi.codegen.model-package=sample.petstore.model +quarkus.camel.openapi.codegen.not-null-jackson=true +camel.rest.bindingMode=json +camel.rest.bindingPackageScan=${quarkus.camel.openapi.codegen.model-package} + +pet.name=Tony the tiger diff --git a/openapi-contract-first/src/test/java/org/acme/examples/openapi/contract/first/ExamplesOpenapiContractFirstIT.java b/openapi-contract-first/src/test/java/org/acme/examples/openapi/contract/first/ExamplesOpenapiContractFirstIT.java new file mode 100644 index 00000000..de03d8cb --- /dev/null +++ b/openapi-contract-first/src/test/java/org/acme/examples/openapi/contract/first/ExamplesOpenapiContractFirstIT.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.acme.examples.openapi.contract.first; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +class ExamplesOpenapiContractFirstIT extends ExamplesOpenapiContractFirstTest { + +} diff --git a/openapi-contract-first/src/test/java/org/acme/examples/openapi/contract/first/ExamplesOpenapiContractFirstTest.java b/openapi-contract-first/src/test/java/org/acme/examples/openapi/contract/first/ExamplesOpenapiContractFirstTest.java new file mode 100644 index 00000000..2cdd12b2 --- /dev/null +++ b/openapi-contract-first/src/test/java/org/acme/examples/openapi/contract/first/ExamplesOpenapiContractFirstTest.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.acme.examples.openapi.contract.first; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.Matchers.is; + +@QuarkusTest +class ExamplesOpenapiContractFirstTest { + + @Test + public void test() { + RestAssured.given() + .contentType(ContentType.JSON) + .get("/api/v3/pet/123") + .then() + .statusCode(200) + .body("id", is(123), "name", is("Tony the tiger"), "status", is("available")); + } +} From a432e11e727485ffafcf986b04b66c092266466d Mon Sep 17 00:00:00 2001 From: Zheng Feng Date: Thu, 23 May 2024 17:20:08 +0800 Subject: [PATCH 2/2] Set quarkus.platform.version to 3.11.0 --- aws-lambda/pom.xml | 2 +- cluster-leader-election/pom.xml | 2 +- cxf-soap/pom.xml | 2 +- file-bindy-ftp/pom.xml | 2 +- file-split-log-xml/pom.xml | 2 +- health/pom.xml | 2 +- http-log/pom.xml | 2 +- jdbc-datasource/pom.xml | 2 +- jms-jpa/pom.xml | 2 +- jpa-idempotent-repository/pom.xml | 2 +- jta-jpa/pom.xml | 2 +- kafka/pom.xml | 2 +- kamelet-chucknorris/pom.xml | 2 +- message-bridge/pom.xml | 2 +- observability/pom.xml | 2 +- openapi-contract-first/pom.xml | 2 +- platform-http-security-keycloak/pom.xml | 2 +- rest-json/pom.xml | 2 +- timer-log-kotlin/pom.xml | 2 +- timer-log-main/pom.xml | 2 +- timer-log/pom.xml | 2 +- vertx-websocket-chat/pom.xml | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/aws-lambda/pom.xml b/aws-lambda/pom.xml index 1764cbb1..eddb1c55 100644 --- a/aws-lambda/pom.xml +++ b/aws-lambda/pom.xml @@ -27,7 +27,7 @@ Camel Quarkus Example :: Deploying a Camel Route in AWS Lambda - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/cluster-leader-election/pom.xml b/cluster-leader-election/pom.xml index 16447c70..f6b833fc 100644 --- a/cluster-leader-election/pom.xml +++ b/cluster-leader-election/pom.xml @@ -29,7 +29,7 @@ Camel Quarkus Example :: Cluster leader election - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/cxf-soap/pom.xml b/cxf-soap/pom.xml index 1813b429..2a320050 100644 --- a/cxf-soap/pom.xml +++ b/cxf-soap/pom.xml @@ -29,7 +29,7 @@ Camel Quarkus Example :: CXF SOAP - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/file-bindy-ftp/pom.xml b/file-bindy-ftp/pom.xml index 880d25a0..71452f85 100644 --- a/file-bindy-ftp/pom.xml +++ b/file-bindy-ftp/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: File Bindy FTP - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/file-split-log-xml/pom.xml b/file-split-log-xml/pom.xml index c41cd2ae..8253afb9 100644 --- a/file-split-log-xml/pom.xml +++ b/file-split-log-xml/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: File To Log XML DSL - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/health/pom.xml b/health/pom.xml index d0ebe532..9e7befa3 100644 --- a/health/pom.xml +++ b/health/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: Health Check - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/http-log/pom.xml b/http-log/pom.xml index 57d14bd2..4afcfcf4 100644 --- a/http-log/pom.xml +++ b/http-log/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: HTTP to Log - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/jdbc-datasource/pom.xml b/jdbc-datasource/pom.xml index 857da08c..39bdf503 100644 --- a/jdbc-datasource/pom.xml +++ b/jdbc-datasource/pom.xml @@ -25,7 +25,7 @@ Camel Quarkus :: Examples :: Jdbc - DatataSource - Log Camel Quarkus Example :: Connect to Database using Datasource - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/jms-jpa/pom.xml b/jms-jpa/pom.xml index fb32c6bf..34b88a88 100644 --- a/jms-jpa/pom.xml +++ b/jms-jpa/pom.xml @@ -25,7 +25,7 @@ Camel Quarkus :: Examples :: JMS JPA Camel Quarkus Example :: JMS JPA - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT 3.3.0 diff --git a/jpa-idempotent-repository/pom.xml b/jpa-idempotent-repository/pom.xml index a83ca13d..7067147e 100644 --- a/jpa-idempotent-repository/pom.xml +++ b/jpa-idempotent-repository/pom.xml @@ -30,7 +30,7 @@ Camel Quarkus Example :: JPA Idempotent Repository - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/jta-jpa/pom.xml b/jta-jpa/pom.xml index c4995e20..8768d4b6 100644 --- a/jta-jpa/pom.xml +++ b/jta-jpa/pom.xml @@ -25,7 +25,7 @@ Camel Quarkus :: Examples :: JTA JPA Camel Quarkus Example :: JTA JPA - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/kafka/pom.xml b/kafka/pom.xml index 0257185a..9492d977 100644 --- a/kafka/pom.xml +++ b/kafka/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: Kafka - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/kamelet-chucknorris/pom.xml b/kamelet-chucknorris/pom.xml index 892f1309..78a95713 100644 --- a/kamelet-chucknorris/pom.xml +++ b/kamelet-chucknorris/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: Kamelet Chuck Norris - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT diff --git a/message-bridge/pom.xml b/message-bridge/pom.xml index 3630a0be..0672209b 100644 --- a/message-bridge/pom.xml +++ b/message-bridge/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: Configure XA Transactions and connection pooling - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/observability/pom.xml b/observability/pom.xml index 58560e3a..7fcafe3c 100644 --- a/observability/pom.xml +++ b/observability/pom.xml @@ -29,7 +29,7 @@ - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/openapi-contract-first/pom.xml b/openapi-contract-first/pom.xml index f8b59493..ad0e6ae9 100644 --- a/openapi-contract-first/pom.xml +++ b/openapi-contract-first/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: openapi-contract-first - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/platform-http-security-keycloak/pom.xml b/platform-http-security-keycloak/pom.xml index a0e715f4..64cf3532 100644 --- a/platform-http-security-keycloak/pom.xml +++ b/platform-http-security-keycloak/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: Platform HTTP Security Keycloak - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/rest-json/pom.xml b/rest-json/pom.xml index 36387ce0..9cde5dcc 100644 --- a/rest-json/pom.xml +++ b/rest-json/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: Rest Json - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/timer-log-kotlin/pom.xml b/timer-log-kotlin/pom.xml index 3215eda0..07337a5b 100644 --- a/timer-log-kotlin/pom.xml +++ b/timer-log-kotlin/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: Timer to Log Kotlin - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/timer-log-main/pom.xml b/timer-log-main/pom.xml index d4752f30..053bc562 100644 --- a/timer-log-main/pom.xml +++ b/timer-log-main/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: Timer to Log Main - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT diff --git a/timer-log/pom.xml b/timer-log/pom.xml index 3b893789..0f6f074c 100644 --- a/timer-log/pom.xml +++ b/timer-log/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: Timer to Log - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus diff --git a/vertx-websocket-chat/pom.xml b/vertx-websocket-chat/pom.xml index 2d7a7377..3c4422db 100644 --- a/vertx-websocket-chat/pom.xml +++ b/vertx-websocket-chat/pom.xml @@ -28,7 +28,7 @@ Camel Quarkus Example :: Implementing Websocket - 3.10.0 + 3.11.0 3.11.0-SNAPSHOT io.quarkus