You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2024/03/28 14:40:14 UTC

(camel) branch openapi2 created (now f8322117479)

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a change to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git


      at f8322117479 Merge branch 'openapi' into openapi2

This branch includes the following new commits:

     new ea8682c1e77 CAMEL-20557: Rest DSL to use openapi spec directly
     new f16ac201f93 CAMEL-20557: Rest DSL to use openapi spec directly
     new 50d3a0bf492 CAMEL-20557: Rest DSL to use openapi spec directly
     new b40dc7c1a80 CAMEL-20557: Rest DSL to use openapi spec directly
     new 00b95c8a944 CAMEL-20557: Rest DSL to use openapi spec directly
     new bed697b46fd CAMEL-20557: Rest DSL to use openapi spec directly
     new dbb28a1754d CAMEL-20557: Rest DSL to use openapi spec directly
     new 443af94082b CAMEL-20557: Rest DSL to use openapi spec directly
     new 8a5b391679c CAMEL-20557: Rest DSL to use openapi spec directly
     new 4467903c031 CAMEL-20557: Rest DSL to use openapi spec directly
     new fd338e08736 CAMEL-20557: Rest DSL to use openapi spec directly
     new f3434923f8f CAMEL-20557: Rest DSL to use openapi spec directly
     new 38a8961e351 CAMEL-20557: Rest DSL to use openapi spec directly
     new bcd4534903c CAMEL-20557: Rest DSL to use openapi spec directly
     new c104cc1762c CAMEL-20557: Rest DSL to use openapi spec directly
     new d1b3aed8b06 CAMEL-20557: Rest DSL to use openapi spec directly
     new a41b4587d37 CAMEL-20557: Rest DSL to use openapi spec directly
     new 9f64e573b6e CAMEL-20557: Rest DSL to use openapi spec directly
     new f76aaf6825e CAMEL-20557: Rest DSL to use openapi spec directly
     new e7991e7f33d CAMEL-20557: Rest DSL to use openapi spec directly
     new f7d730b5d54 CAMEL-20557: Rest DSL to use openapi spec directly
     new d2f1e31090e CAMEL-20557: Rest DSL to use openapi spec directly
     new aded052fde9 CAMEL-20557: Rest DSL to use openapi spec directly
     new 6564e8a2751 CAMEL-20557: Rest DSL to use openapi spec directly
     new b5304ef3b49 CAMEL-20557: Rest DSL to use openapi spec directly
     new d9567498d42 CAMEL-20557: Rest DSL to use openapi spec directly
     new 22b59c69ce7 CAMEL-20557: Rest DSL to use openapi spec directly
     new 8353ab70809 CAMEL-20557: Rest DSL to use openapi spec directly
     new a32952c631a CAMEL-20557: Rest DSL to use openapi spec directly
     new 9356982806e CAMEL-20557: Rest DSL to use openapi spec directly
     new 4d00975a471 CAMEL-20557: Rest DSL to use openapi spec directly
     new e40d5caa3d5 CAMEL-20557: Rest DSL to use openapi spec directly
     new 36bc449ba76 CAMEL-20557: Rest DSL to use openapi spec directly
     new e5b688c502a CAMEL-20557: Rest DSL to use openapi spec directly
     new 0a2c51b7cbd CAMEL-20557: Rest DSL to use openapi spec directly
     new 1e994ed9ac5 CAMEL-20557: Rest DSL to use openapi spec directly
     new cf2d5d01329 CAMEL-20557: Rest DSL to use openapi spec directly
     new f8322117479 Merge branch 'openapi' into openapi2

The 38 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(camel) 07/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit dbb28a1754dfe3658abd86d12b7345864c1b981b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Mar 24 14:35:37 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 components/camel-platform-http-vertx/pom.xml       |    5 +
 .../vertx/PlatformHttpRestOpenApiConsumerTest.java |   57 +
 .../src/test/resources/openapi-v3.json             | 1240 ++++++++++++++++++++
 .../camel/component/rest/openapi/rest-openapi.json |    2 +-
 .../rest/openapi/RestOpenApiComponent.java         |    2 +
 .../rest/openapi/RestOpenApiEndpoint.java          |   42 +-
 .../rest/openapi/RestOpenApiProcessor.java         |    9 +
 7 files changed, 1341 insertions(+), 16 deletions(-)

diff --git a/components/camel-platform-http-vertx/pom.xml b/components/camel-platform-http-vertx/pom.xml
index 6652b203894..665eebb4242 100644
--- a/components/camel-platform-http-vertx/pom.xml
+++ b/components/camel-platform-http-vertx/pom.xml
@@ -89,6 +89,11 @@
             <artifactId>camel-log</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-rest-openapi</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.assertj</groupId>
             <artifactId>assertj-core</artifactId>
diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
new file mode 100644
index 00000000000..7fb2ec61db9
--- /dev/null
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.apache.camel.component.platform.http.vertx;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.equalTo;
+
+public class PlatformHttpRestOpenApiConsumerTest {
+
+    @Test
+    public void testRestOpenApi() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("rest-openapi:classpath:openapi-v3.json")
+                            .log("dummy");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .get("/api/v3/getPetById")
+                    .then()
+                    .statusCode(200)
+                    .body(equalTo("{\"pet\": \"tony the tiger\"}"));
+        } finally {
+            context.stop();
+        }
+    }
+
+}
diff --git a/components/camel-platform-http-vertx/src/test/resources/openapi-v3.json b/components/camel-platform-http-vertx/src/test/resources/openapi-v3.json
new file mode 100644
index 00000000000..b03f018744a
--- /dev/null
+++ b/components/camel-platform-http-vertx/src/test/resources/openapi-v3.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:\ [...]
+		"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/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index b817e5a6551..0c3036935d0 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -39,7 +39,7 @@
     "useGlobalSslContextParameters": { "index": 13, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
-    "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
+    "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not give [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
     "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "bridgeErrorHandler": { "index": 3, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index 497431226a8..019a40cae78 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -151,6 +151,8 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
     protected Endpoint createEndpoint(final String uri, final String remaining, final Map<String, Object> parameters)
             throws Exception {
         RestOpenApiEndpoint endpoint = new RestOpenApiEndpoint(uri, remaining, this, parameters);
+        endpoint.setRequestValidationCustomizer(getRequestValidationCustomizer());
+        endpoint.setRequestValidationEnabled(isRequestValidationEnabled());
         endpoint.setRequestValidationLevels(PropertiesHelper.extractProperties(parameters, "validation."));
         setProperties(endpoint, parameters);
         return endpoint;
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 4e54d21cd7f..c65a309d923 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -76,7 +76,6 @@ import org.apache.camel.support.DefaultEndpoint;
 import org.apache.camel.support.ResourceHelper;
 import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.StringHelper;
 import org.apache.camel.util.UnsafeUriCharactersEncoder;
 import org.apache.commons.io.FileUtils;
 import org.slf4j.Logger;
@@ -84,7 +83,6 @@ import org.slf4j.LoggerFactory;
 
 import static java.util.Optional.ofNullable;
 import static org.apache.camel.component.rest.openapi.RestOpenApiHelper.isHostParam;
-import static org.apache.camel.component.rest.openapi.RestOpenApiHelper.isMediaRange;
 import static org.apache.camel.util.ObjectHelper.isNotEmpty;
 import static org.apache.camel.util.ObjectHelper.notNull;
 import static org.apache.camel.util.StringHelper.after;
@@ -156,8 +154,8 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
                            + " TLS/SSL certificates for https (such as setting a number of javax.net.ssl JVM system properties)."
                            + " How to do that consult the JDK documentation for UrlHandler.",
              defaultValue = RestOpenApiComponent.DEFAULT_SPECIFICATION_URI_STR,
-             defaultValueNote = "By default loads `openapi.json` file", label = "producer")
-    private URI specificationUri = RestOpenApiComponent.DEFAULT_SPECIFICATION_URI;
+             defaultValueNote = "By default loads `openapi.json` file", label = "common")
+    private URI specificationUri;
     @UriParam(description = "Enable validation of requests against the configured OpenAPI specification")
     private boolean requestValidationEnabled;
     @UriParam(description = "If request validation is enabled, this option provides the capability to customize"
@@ -179,12 +177,25 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         super(notEmpty(uri, "uri"), notNull(component, "component"));
         this.parameters = parameters;
 
-        specificationUri = before(remaining, "#", StringHelper::trimToNull)
-                .map(URI::create)
-                .orElse(ofNullable(component.getSpecificationUri()).orElse(RestOpenApiComponent.DEFAULT_SPECIFICATION_URI));
-
-        operationId = ofNullable(after(remaining, "#")).orElse(remaining);
-
+        if (remaining.contains("#")) {
+            operationId = after(remaining, "#");
+            String spec = before(remaining, "#");
+            if (spec != null && !spec.isEmpty()) {
+                specificationUri = URI.create(spec);
+            }
+        } else {
+            if (remaining.endsWith(".json") || remaining.endsWith(".yaml") || remaining.endsWith(".yml")) {
+                specificationUri = URI.create(remaining);
+            } else {
+                operationId = remaining;
+            }
+        }
+        if (specificationUri == null) {
+            specificationUri = component.getSpecificationUri();
+        }
+        if (specificationUri == null) {
+            specificationUri = RestOpenApiComponent.DEFAULT_SPECIFICATION_URI;
+        }
         setExchangePattern(ExchangePattern.InOut);
     }
 
@@ -291,6 +302,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
 
     @Override
     public Producer createProducer() throws Exception {
+
         final CamelContext camelContext = getCamelContext();
         final OpenAPI openapiDoc = loadSpecificationFrom(camelContext, specificationUri);
         final Paths paths = openapiDoc.getPaths();
@@ -371,7 +383,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     }
 
     public void setBasePath(final String basePath) {
-        this.basePath = notEmpty(basePath, "basePath");
+        this.basePath = basePath;
     }
 
     public void setComponentName(final String componentName) {
@@ -383,7 +395,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     }
 
     public void setConsumes(final String consumes) {
-        this.consumes = isMediaRange(consumes, "consumes");
+        this.consumes = consumes;
     }
 
     public void setHost(final String host) {
@@ -391,15 +403,15 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     }
 
     public void setOperationId(final String operationId) {
-        this.operationId = notEmpty(operationId, "operationId");
+        this.operationId = operationId;
     }
 
     public void setProduces(final String produces) {
-        this.produces = isMediaRange(produces, "produces");
+        this.produces = produces;
     }
 
     public void setSpecificationUri(final URI specificationUri) {
-        this.specificationUri = notNull(specificationUri, "specificationUri");
+        this.specificationUri = specificationUri;
     }
 
     public void setRequestValidationCustomizer(
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index 737f14c2643..98409220064 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -17,6 +17,8 @@
 package org.apache.camel.component.rest.openapi;
 
 import io.swagger.v3.oas.models.OpenAPI;
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.support.processor.DelegateAsyncProcessor;
 
@@ -30,4 +32,11 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor {
         this.basePath = basePath;
         this.openAPI = openAPI;
     }
+
+    @Override
+    public boolean process(Exchange exchange, AsyncCallback callback) {
+        // what operation to invoke
+        exchange.getMessage().setBody("I was here");
+        return super.process(exchange, callback);
+    }
 }


(camel) 28/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 8353ab70809e6d7380e51e9f86a8017ba0c6dfd3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 09:14:06 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../org/apache/camel/catalog/models.properties     |   1 +
 .../org/apache/camel/catalog/models/openApi.json   |  20 ++
 .../org/apache/camel/catalog/models/rest.json      |   5 +-
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  28 ++
 ...PlatformHttpRestOpenApiConsumerRestDslTest.java | 281 +++++++++++++++++++++
 .../org/apache/camel/model/rest/openApi.json       |  20 ++
 .../META-INF/org/apache/camel/model/rest/rest.json |   5 +-
 .../services/org/apache/camel/model.properties     |   1 +
 .../org/apache/camel/model/rest/jaxb.index         |   1 +
 .../apache/camel/model/rest/OpenApiDefinition.java |  83 ++++++
 .../apache/camel/model/rest/RestDefinition.java    | 125 ++++++++-
 .../java/org/apache/camel/xml/in/ModelParser.java  |  11 +
 .../java/org/apache/camel/xml/out/ModelWriter.java |  15 ++
 .../org/apache/camel/yaml/out/ModelWriter.java     |  15 ++
 .../dsl/yaml/deserializers/ModelDeserializers.java |  67 +++++
 .../deserializers/ModelDeserializersResolver.java  |   3 +
 .../generated/resources/schema/camelYamlDsl.json   |  33 +++
 17 files changed, 709 insertions(+), 5 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
index 6d987b78e44..5fcbcefbaea 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
@@ -100,6 +100,7 @@ ognl
 onCompletion
 onException
 onFallback
+openApi
 openIdConnect
 optimisticLockRetryPolicy
 otherwise
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json
new file mode 100644
index 00000000000..2fec558b620
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json
@@ -0,0 +1,20 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "openApi",
+    "title": "Open Api",
+    "description": "To use OpenApi as contract-first with Camel Rest DSL.",
+    "deprecated": false,
+    "label": "rest",
+    "javaType": "org.apache.camel.model.rest.OpenApiDefinition",
+    "abstract": false,
+    "input": false,
+    "output": false
+  },
+  "properties": {
+    "id": { "index": 0, "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
+    "description": { "index": 1, "kind": "element", "displayName": "Description", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" },
+    "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST service has been disabled then it cannot be enabled later at runtime." },
+    "specification": { "index": 3, "kind": "attribute", "displayName": "Specification", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false }
+  }
+}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/rest.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/rest.json
index 81e71f12400..f11e6751b04 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/rest.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/rest.json
@@ -25,7 +25,8 @@
     "enableNoContentResponse": { "index": 10, "kind": "attribute", "displayName": "Enable No Content Response", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to return HTTP 204 with an empty body when a response contains an empty JSON object or XML root object. The default value is false." },
     "apiDocs": { "index": 11, "kind": "attribute", "displayName": "Api Docs", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to include or exclude this rest operation in API documentation. This option will override what may be configured on a parent level. The default value is true." },
     "tag": { "index": 12, "kind": "attribute", "displayName": "Tag", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To configure a special tag for the operations within this rest definition." },
-    "securityDefinitions": { "index": 13, "kind": "element", "displayName": "Security Definitions", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.model.rest.RestSecuritiesDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the security definitions such as Basic, OAuth2 etc." },
-    "securityRequirements": { "index": 14, "kind": "element", "displayName": "Security Requirements", "label": "security", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.rest.SecurityDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the security requirement(s) for all endpoints." }
+    "openApi": { "index": 13, "kind": "element", "displayName": "Open Api", "required": false, "type": "object", "javaType": "org.apache.camel.model.rest.OpenApiDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "To use an existing OpenAPI specification as contract-first for Camel Rest DSL." },
+    "securityDefinitions": { "index": 14, "kind": "element", "displayName": "Security Definitions", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.model.rest.RestSecuritiesDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the security definitions such as Basic, OAuth2 etc." },
+    "securityRequirements": { "index": 15, "kind": "element", "displayName": "Security Requirements", "label": "security", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.rest.SecurityDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the security requirement(s) for all endpoints." }
   }
 }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index de2db82edea..53195be2296 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -986,6 +986,15 @@ Route to be executed when an exception is thrown
       <xs:documentation xml:lang="en">
 <![CDATA[
 Route to be executed when Circuit Breaker EIP executes fallback
+]]>
+      </xs:documentation>
+    </xs:annotation>
+  </xs:element>
+  <xs:element name="openApi" type="tns:openApiDefinition">
+    <xs:annotation>
+      <xs:documentation xml:lang="en">
+<![CDATA[
+To use OpenApi as contract-first with Camel Rest DSL.
 ]]>
       </xs:documentation>
     </xs:annotation>
@@ -16368,6 +16377,24 @@ The URL to be used for obtaining refresh tokens. This MUST be in the form of a U
             <xs:documentation xml:lang="en">
 <![CDATA[
 The flow used by the OAuth2 security scheme. Valid values are implicit, password, application or accessCode.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="openApiDefinition">
+    <xs:complexContent>
+      <xs:extension base="tns:optionalIdentifiedDefinition">
+        <xs:sequence/>
+        <xs:attribute name="specification" type="xs:string" use="required"/>
+        <xs:attribute name="disabled" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST
+service has been disabled then it cannot be enabled later at runtime. Default value: false
 ]]>
             </xs:documentation>
           </xs:annotation>
@@ -16819,6 +16846,7 @@ custom name of the data format, not to refer to an existing data format instance
     <xs:complexContent>
       <xs:extension base="tns:optionalIdentifiedDefinition">
         <xs:sequence>
+          <xs:element minOccurs="0" ref="tns:openApi"/>
           <xs:element minOccurs="0" ref="tns:securityDefinitions"/>
           <xs:element maxOccurs="unbounded" minOccurs="0" name="securityRequirements" type="tns:securityDefinition">
             <xs:annotation>
diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
new file mode 100644
index 00000000000..f91954d1ceb
--- /dev/null
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
@@ -0,0 +1,281 @@
+/*
+ * 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.apache.camel.component.platform.http.vertx;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.rest.openapi.RestOpenApiComponent;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.equalToCompressingWhiteSpace;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class PlatformHttpRestOpenApiConsumerRestDslTest {
+
+    @Test
+    public void testRestOpenApi() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
+                    c.setMissingOperation("ignore");
+
+                    rest().openApi("openapi-v3.json");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .get("/api/v3/pet/123")
+                    .then()
+                    .statusCode(200)
+                    .body(equalTo("{\"pet\": \"tony the tiger\"}"));
+
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testRestOpenApiDevMode() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+        // run in developer mode
+        context.getCamelContextExtension().setProfile("dev");
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    rest().openApi("openapi-v3.json");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .get("/api/v3/pet/123")
+                    .then()
+                    .statusCode(200)
+                    .body(equalTo("{\"pet\": \"tony the tiger\"}"));
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testRestOpenApiMock() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
+                    c.setMissingOperation("mock");
+
+                    rest().openApi("openapi-v3.json");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .get("/api/v3/pet/123")
+                    .then()
+                    .statusCode(200)
+                    .body(equalTo("{\"pet\": \"tony the tiger\"}"));
+
+            // mocked gives empty response
+            given()
+                    .when()
+                    .get("/api/v3/pet/findByTags")
+                    .then()
+                    .statusCode(204)
+                    .body(equalTo(""));
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testRestOpenApiMissingOperation() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    rest().openApi("openapi-v3.json");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+            fail();
+        } catch (IllegalArgumentException e) {
+            Assertions.assertTrue(
+                    e.getMessage().startsWith("OpenAPI specification has 18 unmapped operations to corresponding routes"));
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testRestOpenApiNotFound() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
+                    c.setMissingOperation("ignore");
+
+                    rest().openApi("openapi-v3.json");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .get("/api/v3/pet/123/unknown")
+                    .then()
+                    .statusCode(404);
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testRestOpenApiNotAllowed() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
+                    c.setMissingOperation("ignore");
+
+                    rest().openApi("openapi-v3.json");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .put("/api/v3/pet/123")
+                    .then()
+                    .statusCode(405);
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testRestOpenApiValidate() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
+                    c.setMissingOperation("ignore");
+
+                    rest().clientRequestValidation(true).openApi("openapi-v3.json");
+
+                    from("direct:updatePet")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .put("/api/v3/pet")
+                    .then()
+                    .statusCode(405); // no request body
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testRestOpenApiMockData() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
+                    c.setMissingOperation("mock");
+
+                    rest().openApi("openapi-v3.json");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .contentType("application/json")
+                    .get("/api/v3/pet/444")
+                    .then()
+                    .statusCode(200)
+                    .body(equalToCompressingWhiteSpace(
+                            """
+                                    {
+                                      "pet": "donald the dock"
+                                    }"""));
+        } finally {
+            context.stop();
+        }
+    }
+
+}
diff --git a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json
new file mode 100644
index 00000000000..2fec558b620
--- /dev/null
+++ b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json
@@ -0,0 +1,20 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "openApi",
+    "title": "Open Api",
+    "description": "To use OpenApi as contract-first with Camel Rest DSL.",
+    "deprecated": false,
+    "label": "rest",
+    "javaType": "org.apache.camel.model.rest.OpenApiDefinition",
+    "abstract": false,
+    "input": false,
+    "output": false
+  },
+  "properties": {
+    "id": { "index": 0, "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
+    "description": { "index": 1, "kind": "element", "displayName": "Description", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" },
+    "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST service has been disabled then it cannot be enabled later at runtime." },
+    "specification": { "index": 3, "kind": "attribute", "displayName": "Specification", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false }
+  }
+}
diff --git a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/rest.json b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/rest.json
index 81e71f12400..f11e6751b04 100644
--- a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/rest.json
+++ b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/rest.json
@@ -25,7 +25,8 @@
     "enableNoContentResponse": { "index": 10, "kind": "attribute", "displayName": "Enable No Content Response", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to return HTTP 204 with an empty body when a response contains an empty JSON object or XML root object. The default value is false." },
     "apiDocs": { "index": 11, "kind": "attribute", "displayName": "Api Docs", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to include or exclude this rest operation in API documentation. This option will override what may be configured on a parent level. The default value is true." },
     "tag": { "index": 12, "kind": "attribute", "displayName": "Tag", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To configure a special tag for the operations within this rest definition." },
-    "securityDefinitions": { "index": 13, "kind": "element", "displayName": "Security Definitions", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.model.rest.RestSecuritiesDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the security definitions such as Basic, OAuth2 etc." },
-    "securityRequirements": { "index": 14, "kind": "element", "displayName": "Security Requirements", "label": "security", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.rest.SecurityDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the security requirement(s) for all endpoints." }
+    "openApi": { "index": 13, "kind": "element", "displayName": "Open Api", "required": false, "type": "object", "javaType": "org.apache.camel.model.rest.OpenApiDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "To use an existing OpenAPI specification as contract-first for Camel Rest DSL." },
+    "securityDefinitions": { "index": 14, "kind": "element", "displayName": "Security Definitions", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.model.rest.RestSecuritiesDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the security definitions such as Basic, OAuth2 etc." },
+    "securityRequirements": { "index": 15, "kind": "element", "displayName": "Security Requirements", "label": "security", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.rest.SecurityDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the security requirement(s) for all endpoints." }
   }
 }
diff --git a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
index 4d33e1f087c..c6b3ace6879 100644
--- a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
+++ b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
@@ -101,6 +101,7 @@ ognl
 onCompletion
 onException
 onFallback
+openApi
 openIdConnect
 optimisticLockRetryPolicy
 otherwise
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/jaxb.index b/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/jaxb.index
index d5151db1b43..dc35df6c3c5 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/jaxb.index
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/jaxb.index
@@ -8,6 +8,7 @@ GetDefinition
 HeadDefinition
 MutualTLSDefinition
 OAuth2Definition
+OpenApiDefinition
 OpenIdConnectDefinition
 ParamDefinition
 PatchDefinition
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
new file mode 100644
index 00000000000..f2d34c56d81
--- /dev/null
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
@@ -0,0 +1,83 @@
+/*
+ * 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.apache.camel.model.rest;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlAttribute;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.model.OptionalIdentifiedDefinition;
+import org.apache.camel.spi.Metadata;
+
+/**
+ * To use OpenApi as contract-first with Camel Rest DSL.
+ */
+@Metadata(label = "rest")
+@XmlRootElement(name = "openApi")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefinition> {
+
+    @XmlTransient
+    private RestDefinition rest;
+
+    @XmlAttribute(required = true)
+    private String specification;
+    @XmlAttribute
+    @Metadata(label = "advanced", javaType = "java.lang.Boolean")
+    private String disabled;
+
+    @Override
+    public String getShortName() {
+        return "openApi";
+    }
+
+    @Override
+    public String getLabel() {
+        return "openApi";
+    }
+
+    public String getSpecification() {
+        return specification;
+    }
+
+    public void setSpecification(String specification) {
+        this.specification = specification;
+    }
+
+    public String getDisabled() {
+        return disabled;
+    }
+
+    /**
+     * Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST
+     * service has been disabled then it cannot be enabled later at runtime.
+     */
+    public void setDisabled(String disabled) {
+        this.disabled = disabled;
+    }
+
+    // Fluent API
+    // -------------------------------------------------------------------------
+
+    public RestDefinition specification(String specification) {
+        this.specification = specification;
+        return rest;
+    }
+
+}
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
index cb17ab754f9..379d5f46cde 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
@@ -37,6 +37,7 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.model.OptionalIdentifiedDefinition;
 import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.StopDefinition;
 import org.apache.camel.model.ToDefinition;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.NodeIdFactory;
@@ -49,6 +50,7 @@ import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.StringHelper;
 import org.apache.camel.util.URISupport;
 
+import static org.apache.camel.support.CamelContextHelper.parseBoolean;
 import static org.apache.camel.support.CamelContextHelper.parseText;
 
 /**
@@ -90,6 +92,8 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
     @XmlAttribute
     @Metadata(label = "advanced")
     private String tag;
+    @XmlElement
+    private OpenApiDefinition openApi;
     @XmlElement(name = "securityDefinitions") // use the name Swagger/OpenAPI uses
     @Metadata(label = "security")
     private RestSecuritiesDefinition securityDefinitions;
@@ -285,6 +289,17 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
         this.apiDocs = apiDocs;
     }
 
+    public OpenApiDefinition getOpenApi() {
+        return openApi;
+    }
+
+    /**
+     * To use an existing OpenAPI specification as contract-first for Camel Rest DSL.
+     */
+    public void setOpenApi(OpenApiDefinition openApi) {
+        this.openApi = openApi;
+    }
+
     public Resource getResource() {
         return resource;
     }
@@ -296,6 +311,14 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
     // Fluent API
     // -------------------------------------------------------------------------
 
+    /**
+     * To use an existing OpenAPI specification as contract-first for Camel Rest DSL.
+     */
+    public RestDefinition openApi(String specification) {
+        openApi = new OpenApiDefinition();
+        return openApi.specification(specification);
+    }
+
     /**
      * To set the base path of this REST service
      */
@@ -750,6 +773,13 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
         return "rest:" + verb.asVerb() + ":" + buildUri(camelContext, verb);
     }
 
+    /**
+     * Build the from endpoint uri for the open-api
+     */
+    public String buildFromUri(CamelContext camelContext, OpenApiDefinition openApi) {
+        return "rest-openapi:" + parseText(camelContext, openApi.getSpecification());
+    }
+
     // Implementation
     // -------------------------------------------------------------------------
 
@@ -803,6 +833,18 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
             }
         }
 
+        // any open-api contracts
+        if (openApi != null) {
+            disabled = CamelContextHelper.parseBoolean(camelContext, openApi.getDisabled());
+            if (disabled != null && disabled) {
+                openApi = null;
+            }
+        }
+        if (!filter.isEmpty() && openApi != null) {
+            // we cannot have both code-first and contract-first in rest-dsl
+            throw new IllegalArgumentException("Cannot have both code-first and contract-first in Rest DSL");
+        }
+
         // sanity check this rest definition do not have duplicates
         validateUniquePaths(filter);
 
@@ -811,7 +853,12 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
             // sanity check this rest definition do not have duplicates linked routes via direct endpoints
             validateUniqueDirects(filter);
         }
-        addRouteDefinition(camelContext, filter, answer, config.getComponent(), config.getProducerComponent());
+        if (!filter.isEmpty()) {
+            addRouteDefinition(camelContext, filter, answer, config.getComponent(), config.getProducerComponent());
+        }
+        if (openApi != null) {
+            addRouteDefinition(camelContext, openApi, answer, config.getComponent(), config.getProducerComponent());
+        }
 
         return answer;
     }
@@ -909,6 +956,82 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
     }
 
     @SuppressWarnings("rawtypes")
+    private void addRouteDefinition(
+            CamelContext camelContext, OpenApiDefinition openApi, List<RouteDefinition> answer,
+            String component, String producerComponent) {
+
+        RouteDefinition route = new RouteDefinition();
+        // add dummy empty stop
+        route.getOutputs().add(new StopDefinition());
+
+        RestBindingDefinition binding = new RestBindingDefinition();
+        binding.setComponent(component);
+        if (binding.getBindingMode() != null) {
+            String mode = binding.getBindingMode();
+            if ("json".equals(mode)) {
+                binding.setConsumes("application/json");
+                binding.setProduces("application/json");
+            } else if ("xml".equals(mode)) {
+                binding.setConsumes("application/xml");
+                binding.setProduces("application/xml");
+            } else if ("json_xml".equals(mode)) {
+                binding.setConsumes("application/json;application/xml");
+                binding.setProduces("application/json;application/xml");
+            }
+        }
+        binding.setSkipBindingOnErrorCode(getSkipBindingOnErrorCode());
+        binding.setClientRequestValidation(getClientRequestValidation());
+        binding.setEnableCORS(getEnableCORS());
+        binding.setEnableNoContentResponse(getEnableNoContentResponse());
+
+        route.setRestBindingDefinition(binding);
+
+        // append options
+        Map<String, Object> options = new HashMap<>();
+        if (binding.getConsumes() != null) {
+            options.put("consumes", binding.getConsumes());
+        }
+        if (binding.getProduces() != null) {
+            options.put("produces", binding.getProduces());
+        }
+        if (component != null && !component.isEmpty()) {
+            options.put("consumerComponentName", component);
+        }
+        if (producerComponent != null && !producerComponent.isEmpty()) {
+            options.put("producerComponentName", producerComponent);
+        }
+        Boolean validate = parseBoolean(camelContext, getClientRequestValidation());
+        if (validate != null && validate) {
+            options.put("requestValidationEnabled", "true");
+        }
+
+        // include optional description
+        String description = openApi.getDescription();
+        if (description == null) {
+            description = getDescriptionText();
+        }
+        if (description != null) {
+            options.put("description", parseText(camelContext, description));
+        }
+
+        // create the from endpoint uri which is using the rest-openapi component
+        String from = buildFromUri(camelContext, openApi);
+
+        // append additional options
+        if (!options.isEmpty()) {
+            try {
+                from = URISupport.appendParametersToURI(from, options);
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeCamelException(e);
+            }
+        }
+
+        // the route should be from this rest endpoint
+        route.fromRest(from);
+        route.setRestDefinition(this);
+        answer.add(route);
+    }
+
     private void addRouteDefinition(
             CamelContext camelContext, List<VerbDefinition> verbs, List<RouteDefinition> answer,
             String component, String producerComponent) {
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index 0befa365a29..754fdcd576c 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -1121,6 +1121,7 @@ public class ModelParser extends BaseParser {
                 case "patch": doAdd(doParsePatchDefinition(), def.getVerbs(), def::setVerbs); break;
                 case "post": doAdd(doParsePostDefinition(), def.getVerbs(), def::setVerbs); break;
                 case "put": doAdd(doParsePutDefinition(), def.getVerbs(), def::setVerbs); break;
+                case "openApi": def.setOpenApi(doParseOpenApiDefinition()); break;
                 case "securityDefinitions": def.setSecurityDefinitions(doParseRestSecuritiesDefinition()); break;
                 case "securityRequirements": doAdd(doParseSecurityDefinition(), def.getSecurityRequirements(), def::setSecurityRequirements); break;
                 default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
@@ -3298,6 +3299,16 @@ public class ModelParser extends BaseParser {
             return true;
         }, noElementHandler(), noValueHandler());
     }
+    protected OpenApiDefinition doParseOpenApiDefinition() throws IOException, XmlPullParserException {
+        return doParse(new OpenApiDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "disabled": def.setDisabled(val); break;
+                case "specification": def.setSpecification(val); break;
+                default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
     protected OpenIdConnectDefinition doParseOpenIdConnectDefinition() throws IOException, XmlPullParserException {
         return doParse(new OpenIdConnectDefinition(), (def, key, val) -> {
             if ("url".equals(key)) {
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index f4ea46fe3c5..86c297846c1 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -981,6 +981,9 @@ public class ModelWriter extends BaseWriter {
     public void writeOAuth2Definition(OAuth2Definition def) throws IOException {
         doWriteOAuth2Definition("oauth2", def);
     }
+    public void writeOpenApiDefinition(OpenApiDefinition def) throws IOException {
+        doWriteOpenApiDefinition("openApi", def);
+    }
     public void writeOpenIdConnectDefinition(
             OpenIdConnectDefinition def)
             throws IOException {
@@ -4410,6 +4413,16 @@ public class ModelWriter extends BaseWriter {
         doWriteList(null, "scopes", def.getScopes(), this::doWriteRestPropertyDefinition);
         endElement(name);
     }
+    protected void doWriteOpenApiDefinition(
+            String name,
+            OpenApiDefinition def)
+            throws IOException {
+        startElement(name);
+        doWriteOptionalIdentifiedDefinitionAttributes(def);
+        doWriteAttribute("specification", def.getSpecification());
+        doWriteAttribute("disabled", def.getDisabled());
+        endElement(name);
+    }
     protected void doWriteOpenIdConnectDefinition(
             String name,
             OpenIdConnectDefinition def)
@@ -4561,6 +4574,7 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("disabled", def.getDisabled());
         doWriteAttribute("tag", def.getTag());
         doWriteAttribute("consumes", def.getConsumes());
+        doWriteElement("openApi", def.getOpenApi(), this::doWriteOpenApiDefinition);
         doWriteList(null, "securityRequirements", def.getSecurityRequirements(), this::doWriteSecurityDefinition);
         doWriteList(null, null, def.getVerbs(), this::doWriteVerbDefinitionRef);
         doWriteElement("securityDefinitions", def.getSecurityDefinitions(), this::doWriteRestSecuritiesDefinition);
@@ -4939,6 +4953,7 @@ public class ModelWriter extends BaseWriter {
                 case "DeleteDefinition" -> doWriteDeleteDefinition("delete", (DeleteDefinition) v);
                 case "GetDefinition" -> doWriteGetDefinition("get", (GetDefinition) v);
                 case "HeadDefinition" -> doWriteHeadDefinition("head", (HeadDefinition) v);
+                case "OpenApiDefinition" -> doWriteOpenApiDefinition("openApi", (OpenApiDefinition) v);
                 case "PatchDefinition" -> doWritePatchDefinition("patch", (PatchDefinition) v);
                 case "PostDefinition" -> doWritePostDefinition("post", (PostDefinition) v);
                 case "PutDefinition" -> doWritePutDefinition("put", (PutDefinition) v);
diff --git a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index 1de6d98bbfd..00ba07c5722 100644
--- a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++ b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -981,6 +981,9 @@ public class ModelWriter extends BaseWriter {
     public void writeOAuth2Definition(OAuth2Definition def) throws IOException {
         doWriteOAuth2Definition("oauth2", def);
     }
+    public void writeOpenApiDefinition(OpenApiDefinition def) throws IOException {
+        doWriteOpenApiDefinition("openApi", def);
+    }
     public void writeOpenIdConnectDefinition(
             OpenIdConnectDefinition def)
             throws IOException {
@@ -4410,6 +4413,16 @@ public class ModelWriter extends BaseWriter {
         doWriteList(null, "scopes", def.getScopes(), this::doWriteRestPropertyDefinition);
         endElement(name);
     }
+    protected void doWriteOpenApiDefinition(
+            String name,
+            OpenApiDefinition def)
+            throws IOException {
+        startElement(name);
+        doWriteOptionalIdentifiedDefinitionAttributes(def);
+        doWriteAttribute("specification", def.getSpecification());
+        doWriteAttribute("disabled", def.getDisabled());
+        endElement(name);
+    }
     protected void doWriteOpenIdConnectDefinition(
             String name,
             OpenIdConnectDefinition def)
@@ -4561,6 +4574,7 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("disabled", def.getDisabled());
         doWriteAttribute("tag", def.getTag());
         doWriteAttribute("consumes", def.getConsumes());
+        doWriteElement("openApi", def.getOpenApi(), this::doWriteOpenApiDefinition);
         doWriteList(null, "securityRequirements", def.getSecurityRequirements(), this::doWriteSecurityDefinition);
         doWriteList(null, null, def.getVerbs(), this::doWriteVerbDefinitionRef);
         doWriteElement("securityDefinitions", def.getSecurityDefinitions(), this::doWriteRestSecuritiesDefinition);
@@ -4939,6 +4953,7 @@ public class ModelWriter extends BaseWriter {
                 case "DeleteDefinition" -> doWriteDeleteDefinition("delete", (DeleteDefinition) v);
                 case "GetDefinition" -> doWriteGetDefinition("get", (GetDefinition) v);
                 case "HeadDefinition" -> doWriteHeadDefinition("head", (HeadDefinition) v);
+                case "OpenApiDefinition" -> doWriteOpenApiDefinition("openApi", (OpenApiDefinition) v);
                 case "PatchDefinition" -> doWritePatchDefinition("patch", (PatchDefinition) v);
                 case "PostDefinition" -> doWritePostDefinition("post", (PostDefinition) v);
                 case "PutDefinition" -> doWritePutDefinition("put", (PutDefinition) v);
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index 6e27b84e32f..2080a28405f 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -223,6 +223,7 @@ import org.apache.camel.model.rest.GetDefinition;
 import org.apache.camel.model.rest.HeadDefinition;
 import org.apache.camel.model.rest.MutualTLSDefinition;
 import org.apache.camel.model.rest.OAuth2Definition;
+import org.apache.camel.model.rest.OpenApiDefinition;
 import org.apache.camel.model.rest.OpenIdConnectDefinition;
 import org.apache.camel.model.rest.ParamDefinition;
 import org.apache.camel.model.rest.PatchDefinition;
@@ -10345,6 +10346,66 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
     }
 
+    @YamlType(
+            nodes = {
+                    "open-api",
+                    "openApi"
+            },
+            types = org.apache.camel.model.rest.OpenApiDefinition.class,
+            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
+            displayName = "Open Api",
+            description = "To use OpenApi as contract-first with Camel Rest DSL.",
+            deprecated = false,
+            properties = {
+                    @YamlProperty(name = "description", type = "string", description = "Sets the description of this node", displayName = "Description"),
+                    @YamlProperty(name = "disabled", type = "boolean", description = "Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST service has been disabled then it cannot be enabled later at runtime.", displayName = "Disabled"),
+                    @YamlProperty(name = "id", type = "string", description = "Sets the id of this node", displayName = "Id"),
+                    @YamlProperty(name = "specification", type = "string", required = true, displayName = "Specification")
+            }
+    )
+    public static class OpenApiDefinitionDeserializer extends YamlDeserializerBase<OpenApiDefinition> {
+        public OpenApiDefinitionDeserializer() {
+            super(OpenApiDefinition.class);
+        }
+
+        @Override
+        protected OpenApiDefinition newInstance() {
+            return new OpenApiDefinition();
+        }
+
+        @Override
+        protected boolean setProperty(OpenApiDefinition target, String propertyKey,
+                String propertyName, Node node) {
+            propertyKey = org.apache.camel.util.StringHelper.dashToCamelCase(propertyKey);
+            switch(propertyKey) {
+                case "disabled": {
+                    String val = asText(node);
+                    target.setDisabled(val);
+                    break;
+                }
+                case "specification": {
+                    String val = asText(node);
+                    target.setSpecification(val);
+                    break;
+                }
+                case "id": {
+                    String val = asText(node);
+                    target.setId(val);
+                    break;
+                }
+                case "description": {
+                    String val = asText(node);
+                    target.setDescription(val);
+                    break;
+                }
+                default: {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
     @YamlType(
             nodes = {
                     "open-id-connect",
@@ -14053,6 +14114,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "get", type = "array:org.apache.camel.model.rest.GetDefinition"),
                     @YamlProperty(name = "head", type = "array:org.apache.camel.model.rest.HeadDefinition"),
                     @YamlProperty(name = "id", type = "string", description = "Sets the id of this node", displayName = "Id"),
+                    @YamlProperty(name = "openApi", type = "object:org.apache.camel.model.rest.OpenApiDefinition", description = "To use an existing OpenAPI specification as contract-first for Camel Rest DSL.", displayName = "Open Api"),
                     @YamlProperty(name = "patch", type = "array:org.apache.camel.model.rest.PatchDefinition"),
                     @YamlProperty(name = "path", type = "string", description = "Path of the rest service, such as /foo", displayName = "Path"),
                     @YamlProperty(name = "post", type = "array:org.apache.camel.model.rest.PostDefinition"),
@@ -14114,6 +14176,11 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setEnableNoContentResponse(val);
                     break;
                 }
+                case "openApi": {
+                    org.apache.camel.model.rest.OpenApiDefinition val = asType(node, org.apache.camel.model.rest.OpenApiDefinition.class);
+                    target.setOpenApi(val);
+                    break;
+                }
                 case "path": {
                     String val = asText(node);
                     target.setPath(val);
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index bf7c90a66be..371d2857f8f 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -270,6 +270,9 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "on-fallback": return new ModelDeserializers.OnFallbackDefinitionDeserializer();
             case "onFallback": return new ModelDeserializers.OnFallbackDefinitionDeserializer();
             case "org.apache.camel.model.OnFallbackDefinition": return new ModelDeserializers.OnFallbackDefinitionDeserializer();
+            case "open-api": return new ModelDeserializers.OpenApiDefinitionDeserializer();
+            case "openApi": return new ModelDeserializers.OpenApiDefinitionDeserializer();
+            case "org.apache.camel.model.rest.OpenApiDefinition": return new ModelDeserializers.OpenApiDefinitionDeserializer();
             case "open-id-connect": return new ModelDeserializers.OpenIdConnectDefinitionDeserializer();
             case "openIdConnect": return new ModelDeserializers.OpenIdConnectDefinitionDeserializer();
             case "org.apache.camel.model.rest.OpenIdConnectDefinition": return new ModelDeserializers.OpenIdConnectDefinitionDeserializer();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index 96c44926b48..00d55240b25 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -14668,6 +14668,34 @@
         },
         "required" : [ "key" ]
       },
+      "org.apache.camel.model.rest.OpenApiDefinition" : {
+        "title" : "Open Api",
+        "description" : "To use OpenApi as contract-first with Camel Rest DSL.",
+        "type" : "object",
+        "additionalProperties" : false,
+        "properties" : {
+          "description" : {
+            "type" : "string",
+            "title" : "Description",
+            "description" : "Sets the description of this node"
+          },
+          "disabled" : {
+            "type" : "boolean",
+            "title" : "Disabled",
+            "description" : "Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST service has been disabled then it cannot be enabled later at runtime."
+          },
+          "id" : {
+            "type" : "string",
+            "title" : "Id",
+            "description" : "Sets the id of this node"
+          },
+          "specification" : {
+            "type" : "string",
+            "title" : "Specification"
+          }
+        },
+        "required" : [ "specification" ]
+      },
       "org.apache.camel.model.rest.OpenIdConnectDefinition" : {
         "title" : "Open Id Connect",
         "description" : "Rest security OpenID Connect definition",
@@ -15518,6 +15546,11 @@
             "title" : "Id",
             "description" : "Sets the id of this node"
           },
+          "openApi" : {
+            "title" : "Open Api",
+            "description" : "To use an existing OpenAPI specification as contract-first for Camel Rest DSL.",
+            "$ref" : "#/items/definitions/org.apache.camel.model.rest.OpenApiDefinition"
+          },
           "patch" : {
             "type" : "array",
             "items" : {


(camel) 23/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit aded052fde90eb152a2dd6668c4f196a4bfc23a3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 17:15:45 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../DefaultRestOpenapiProcessorStrategy.java       | 50 +++++++++++-----------
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index bd873724294..2659e57880e 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -124,35 +124,35 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         final PackageScanResourceResolver resolver = PluginHelper.getPackageScanResourceResolver(camelContext);
         final String[] includes = mockIncludePattern != null ? mockIncludePattern.split(",") : null;
 
-        Collection<Resource> accepted = new ArrayList<>();
-        for (String include : includes) {
-            try {
-                for (Resource resource : resolver.findResources(include)) {
-                    accepted.add(resource);
+        Resource found = null;
+        if (includes != null) {
+            Collection<Resource> accepted = new ArrayList<>();
+            for (String include : includes) {
+                try {
+                    accepted.addAll(resolver.findResources(include));
+                } catch (Exception e) {
+                    throw RuntimeCamelException.wrapRuntimeException(e);
                 }
-            } catch (Exception e) {
-                throw RuntimeCamelException.wrapRuntimeException(e);
             }
-        }
 
-        boolean json = false;
-        boolean xml = false;
-        String ct = ExchangeHelper.getContentType(exchange);
-        if (ct != null) {
-            json = ct.contains("json");
-            xml = ct.contains("xml");
-        }
+            boolean json = false;
+            boolean xml = false;
+            String ct = ExchangeHelper.getContentType(exchange);
+            if (ct != null) {
+                json = ct.contains("json");
+                xml = ct.contains("xml");
+            }
 
-        Resource found = null;
-        for (Resource resource : accepted) {
-            String target = FileUtil.stripFirstLeadingSeparator(path);
-            String loc = FileUtil.stripExt(FileUtil.compactPath(resource.getLocation(), '/'));
-            String onlyExt = FileUtil.onlyExt(resource.getLocation());
-            boolean match = loc.endsWith(target);
-            boolean matchExt = !json && !xml || json && onlyExt.equals("json") || xml && onlyExt.equals("xml");
-            if (match && matchExt) {
-                found = resource;
-                break;
+            for (Resource resource : accepted) {
+                String target = FileUtil.stripFirstLeadingSeparator(path);
+                String loc = FileUtil.stripExt(FileUtil.compactPath(resource.getLocation(), '/'));
+                String onlyExt = FileUtil.onlyExt(resource.getLocation());
+                boolean match = loc.endsWith(target);
+                boolean matchExt = !json && !xml || json && onlyExt.equals("json") || xml && onlyExt.equals("xml");
+                if (match && matchExt) {
+                    found = resource;
+                    break;
+                }
             }
         }
         if (found != null) {


(camel) 11/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit fd338e087360564a40213b61d478ea565a0c52a3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 09:39:32 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../camel/catalog/components/rest-openapi.json     |  40 ++++----
 .../openapi/RestOpenApiComponentConfigurer.java    |   6 ++
 .../openapi/RestOpenApiEndpointConfigurer.java     |   6 ++
 .../openapi/RestOpenApiEndpointUriFactory.java     |   3 +-
 .../camel/component/rest/openapi/rest-openapi.json |  40 ++++----
 .../DefaultRestOpenapiProcessorStrategy.java       |  18 +++-
 .../rest/openapi/RestOpenApiComponent.java         |  11 +++
 .../rest/openapi/RestOpenApiEndpoint.java          |  18 ++--
 .../rest/openapi/RestOpenapiProcessorStrategy.java |  15 +++
 .../dsl/RestOpenapiComponentBuilderFactory.java    | 102 +++++++++++++++++----
 .../src/generated/resources/metadata.json          |   2 +-
 .../dsl/RestOpenApiEndpointBuilderFactory.java     |  32 +++++++
 .../camel/kotlin/components/RestOpenapiUriDsl.kt   |   7 ++
 13 files changed, 234 insertions(+), 66 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index 0c3036935d0..22998ee020e 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -26,17 +26,18 @@
     "requestValidationEnabled": { "index": 0, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
     "consumerComponentName": { "index": 2, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "basePath": { "index": 3, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
-    "host": { "index": 4, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 5, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "specificationUri": { "index": 6, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
-    "componentName": { "index": 7, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
-    "consumes": { "index": 8, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
-    "produces": { "index": 9, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi sp [...]
-    "autowiredEnabled": { "index": 10, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
-    "requestValidationCustomizer": { "index": 11, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
-    "sslContextParameters": { "index": 12, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
-    "useGlobalSslContextParameters": { "index": 13, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
+    "restOpenapiProcessorStrategy": { "index": 3, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 4, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
+    "host": { "index": 5, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 6, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "specificationUri": { "index": 7, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
+    "componentName": { "index": 8, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
+    "consumes": { "index": 9, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
+    "produces": { "index": 10, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
+    "autowiredEnabled": { "index": 11, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
+    "requestValidationCustomizer": { "index": 12, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
+    "sslContextParameters": { "index": 13, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
+    "useGlobalSslContextParameters": { "index": 14, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not give [...]
@@ -46,13 +47,14 @@
     "consumerComponentName": { "index": 4, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
     "exceptionHandler": { "index": 5, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
     "exchangePattern": { "index": 6, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
-    "basePath": { "index": 7, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "consumes": { "index": 8, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
-    "host": { "index": 9, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
-    "produces": { "index": 10, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
-    "componentName": { "index": 11, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
-    "lazyStartProducer": { "index": 12, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
-    "requestValidationCustomizer": { "index": 13, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
-    "requestValidationLevels": { "index": 14, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
+    "restOpenapiProcessorStrategy": { "index": 7, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 8, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
+    "consumes": { "index": 9, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
+    "host": { "index": 10, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
+    "produces": { "index": 11, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
+    "componentName": { "index": 12, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
+    "lazyStartProducer": { "index": 13, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "requestValidationCustomizer": { "index": 14, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
+    "requestValidationLevels": { "index": 15, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
index ba22d771a42..89b6cc3ccc6 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
@@ -40,6 +40,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "requestValidationCustomizer": target.setRequestValidationCustomizer(property(camelContext, org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer.class, value)); return true;
         case "requestvalidationenabled":
         case "requestValidationEnabled": target.setRequestValidationEnabled(property(camelContext, boolean.class, value)); return true;
+        case "restopenapiprocessorstrategy":
+        case "restOpenapiProcessorStrategy": target.setRestOpenapiProcessorStrategy(property(camelContext, org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy.class, value)); return true;
         case "specificationuri":
         case "specificationUri": target.setSpecificationUri(property(camelContext, java.net.URI.class, value)); return true;
         case "sslcontextparameters":
@@ -72,6 +74,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "requestValidationCustomizer": return org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer.class;
         case "requestvalidationenabled":
         case "requestValidationEnabled": return boolean.class;
+        case "restopenapiprocessorstrategy":
+        case "restOpenapiProcessorStrategy": return org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy.class;
         case "specificationuri":
         case "specificationUri": return java.net.URI.class;
         case "sslcontextparameters":
@@ -105,6 +109,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "requestValidationCustomizer": return target.getRequestValidationCustomizer();
         case "requestvalidationenabled":
         case "requestValidationEnabled": return target.isRequestValidationEnabled();
+        case "restopenapiprocessorstrategy":
+        case "restOpenapiProcessorStrategy": return target.getRestOpenapiProcessorStrategy();
         case "specificationuri":
         case "specificationUri": return target.getSpecificationUri();
         case "sslcontextparameters":
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
index 3c8adaec8e9..7877105d046 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
@@ -44,6 +44,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         case "requestValidationEnabled": target.setRequestValidationEnabled(property(camelContext, boolean.class, value)); return true;
         case "requestvalidationlevels":
         case "requestValidationLevels": target.setRequestValidationLevels(property(camelContext, java.util.Map.class, value)); return true;
+        case "restopenapiprocessorstrategy":
+        case "restOpenapiProcessorStrategy": target.setRestOpenapiProcessorStrategy(property(camelContext, org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy.class, value)); return true;
         default: return false;
         }
     }
@@ -74,6 +76,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         case "requestValidationEnabled": return boolean.class;
         case "requestvalidationlevels":
         case "requestValidationLevels": return java.util.Map.class;
+        case "restopenapiprocessorstrategy":
+        case "restOpenapiProcessorStrategy": return org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy.class;
         default: return null;
         }
     }
@@ -105,6 +109,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         case "requestValidationEnabled": return target.isRequestValidationEnabled();
         case "requestvalidationlevels":
         case "requestValidationLevels": return target.getRequestValidationLevels();
+        case "restopenapiprocessorstrategy":
+        case "restOpenapiProcessorStrategy": return target.getRestOpenapiProcessorStrategy();
         default: return null;
         }
     }
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
index 8cf0fd1124f..1117c2366cf 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
@@ -21,7 +21,7 @@ public class RestOpenApiEndpointUriFactory extends org.apache.camel.support.comp
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(15);
+        Set<String> props = new HashSet<>(16);
         props.add("basePath");
         props.add("bridgeErrorHandler");
         props.add("componentName");
@@ -36,6 +36,7 @@ public class RestOpenApiEndpointUriFactory extends org.apache.camel.support.comp
         props.add("requestValidationCustomizer");
         props.add("requestValidationEnabled");
         props.add("requestValidationLevels");
+        props.add("restOpenapiProcessorStrategy");
         props.add("specificationUri");
         PROPERTY_NAMES = Collections.unmodifiableSet(props);
         SECRET_PROPERTY_NAMES = Collections.emptySet();
diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index 0c3036935d0..22998ee020e 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -26,17 +26,18 @@
     "requestValidationEnabled": { "index": 0, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
     "consumerComponentName": { "index": 2, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "basePath": { "index": 3, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
-    "host": { "index": 4, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 5, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "specificationUri": { "index": 6, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
-    "componentName": { "index": 7, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
-    "consumes": { "index": 8, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
-    "produces": { "index": 9, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi sp [...]
-    "autowiredEnabled": { "index": 10, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
-    "requestValidationCustomizer": { "index": 11, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
-    "sslContextParameters": { "index": 12, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
-    "useGlobalSslContextParameters": { "index": 13, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
+    "restOpenapiProcessorStrategy": { "index": 3, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 4, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
+    "host": { "index": 5, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 6, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "specificationUri": { "index": 7, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
+    "componentName": { "index": 8, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
+    "consumes": { "index": 9, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
+    "produces": { "index": 10, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
+    "autowiredEnabled": { "index": 11, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
+    "requestValidationCustomizer": { "index": 12, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
+    "sslContextParameters": { "index": 13, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
+    "useGlobalSslContextParameters": { "index": 14, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not give [...]
@@ -46,13 +47,14 @@
     "consumerComponentName": { "index": 4, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
     "exceptionHandler": { "index": 5, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
     "exchangePattern": { "index": 6, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
-    "basePath": { "index": 7, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "consumes": { "index": 8, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
-    "host": { "index": 9, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
-    "produces": { "index": 10, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
-    "componentName": { "index": 11, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
-    "lazyStartProducer": { "index": 12, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
-    "requestValidationCustomizer": { "index": 13, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
-    "requestValidationLevels": { "index": 14, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
+    "restOpenapiProcessorStrategy": { "index": 7, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 8, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
+    "consumes": { "index": 9, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
+    "host": { "index": 10, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
+    "produces": { "index": 11, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
+    "componentName": { "index": 12, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
+    "lazyStartProducer": { "index": 13, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "requestValidationCustomizer": { "index": 14, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
+    "requestValidationLevels": { "index": 15, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index 965b9625519..b46795d5a46 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -29,15 +29,19 @@ import org.apache.camel.support.cache.DefaultProducerCache;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.support.service.ServiceSupport;
 
+/**
+ * Default {@link RestOpenapiProcessorStrategy} that links the Rest DSL to routes called via direct:operationId.
+ */
 public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         implements RestOpenapiProcessorStrategy, CamelContextAware, NonManagedService {
 
     private CamelContext camelContext;
     private ProducerCache producerCache;
+    private String component = "direct";
 
     @Override
     public boolean process(Operation operation, String path, Exchange exchange, AsyncCallback callback) {
-        Endpoint e = camelContext.getEndpoint("direct:" + operation.getOperationId());
+        Endpoint e = camelContext.getEndpoint(component + ":" + operation.getOperationId());
         AsyncProducer p = producerCache.acquireProducer(e);
         return p.process(exchange, doneSync -> {
             try {
@@ -58,9 +62,19 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         this.camelContext = camelContext;
     }
 
+    public String getComponent() {
+        return component;
+    }
+
+    /**
+     * Name of component to use for processing the Rest DSL requests.
+     */
+    public void setComponent(String component) {
+        this.component = component;
+    }
+
     @Override
     protected void doInit() throws Exception {
-        // TODO: non-managed
         producerCache = new DefaultProducerCache(this, getCamelContext(), 1000);
         ServiceHelper.initService(producerCache);
     }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index 019a40cae78..eef794e5371 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -139,6 +139,8 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
     @Metadata(description = "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context ",
               label = "security")
     private SSLContextParameters sslContextParameters;
+    @Metadata(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
+    private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
 
     public RestOpenApiComponent() {
     }
@@ -154,6 +156,7 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         endpoint.setRequestValidationCustomizer(getRequestValidationCustomizer());
         endpoint.setRequestValidationEnabled(isRequestValidationEnabled());
         endpoint.setRequestValidationLevels(PropertiesHelper.extractProperties(parameters, "validation."));
+        endpoint.setRestOpenapiProcessorStrategy(getRestOpenapiProcessorStrategy());
         setProperties(endpoint, parameters);
         return endpoint;
     }
@@ -195,6 +198,14 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         return useGlobalSslContextParameters;
     }
 
+    public RestOpenapiProcessorStrategy getRestOpenapiProcessorStrategy() {
+        return restOpenapiProcessorStrategy;
+    }
+
+    public void setRestOpenapiProcessorStrategy(RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) {
+        this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy;
+    }
+
     public void setBasePath(final String basePath) {
         this.basePath = notEmpty(basePath, "basePath");
     }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index c6b8eca82f9..21fde6f5618 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -82,13 +82,10 @@ import org.apache.commons.io.FileUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static java.util.Optional.ofNullable;
 import static org.apache.camel.component.rest.openapi.RestOpenApiHelper.isHostParam;
 import static org.apache.camel.util.ObjectHelper.isNotEmpty;
-import static org.apache.camel.util.ObjectHelper.notNull;
 import static org.apache.camel.util.StringHelper.after;
 import static org.apache.camel.util.StringHelper.before;
-import static org.apache.camel.util.StringHelper.notEmpty;
 
 /**
  * To call REST services using OpenAPI specification as contract.
@@ -168,6 +165,8 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
                             + "&validation.request.body.unexpected=IGNORED. Supported values are INFO, ERROR, WARN & IGNORE.",
               label = "advanced", prefix = "validation.", multiValue = true)
     private Map<String, Object> requestValidationLevels = new HashMap<>();
+    @UriParam(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
+    private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy;
 
     public RestOpenApiEndpoint() {
         // help tooling instantiate endpoint
@@ -175,9 +174,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
 
     public RestOpenApiEndpoint(final String uri, final String remaining, final RestOpenApiComponent component,
                                final Map<String, Object> parameters) {
-        super(notEmpty(uri, "uri"), notNull(component, "component"));
-        this.parameters = parameters;
-
+        super(uri, component);
         if (remaining.contains("#")) {
             operationId = after(remaining, "#");
             String spec = before(remaining, "#");
@@ -197,6 +194,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         if (specificationUri == null) {
             specificationUri = RestOpenApiComponent.DEFAULT_SPECIFICATION_URI;
         }
+        this.parameters = parameters;
         setExchangePattern(ExchangePattern.InOut);
     }
 
@@ -442,6 +440,14 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         return requestValidationLevels;
     }
 
+    public RestOpenapiProcessorStrategy getRestOpenapiProcessorStrategy() {
+        return restOpenapiProcessorStrategy;
+    }
+
+    public void setRestOpenapiProcessorStrategy(RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) {
+        this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy;
+    }
+
     Producer createProducerFor(
             final OpenAPI openapi, final Operation operation, final String method,
             final String uriTemplate)
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
index baaeac1d81e..80fb0501865 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
@@ -20,8 +20,23 @@ import io.swagger.v3.oas.models.Operation;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.Exchange;
 
+/**
+ * Strategy for processing the Rest DSL that services an OpenAPI spec.
+ */
 public interface RestOpenapiProcessorStrategy {
 
+    /**
+     * Strategy for processing the Rest DSL operation
+     *
+     * @param  operation the rest operation
+     * @param  path      the context-path
+     * @param  exchange  the exchange
+     * @param  callback  the AsyncCallback will be invoked when the processing of the exchange is completed. If the
+     *                   exchange is completed synchronously, then the callback is also invoked synchronously. The
+     *                   callback should therefore be careful of starting recursive loop.
+     * @return           (doneSync) true to continue execute synchronously, false to continue being executed
+     *                   asynchronously
+     */
     boolean process(Operation operation, String path, Exchange exchange, AsyncCallback callback);
 
 }
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
index 3a2f0efae63..077b716fab2 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
@@ -50,6 +50,86 @@ public interface RestOpenapiComponentBuilderFactory {
     interface RestOpenapiComponentBuilder
             extends
                 ComponentBuilder<RestOpenApiComponent> {
+        /**
+         * Enable validation of requests against the configured OpenAPI
+         * specification.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param requestValidationEnabled the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder requestValidationEnabled(
+                boolean requestValidationEnabled) {
+            doSetProperty("requestValidationEnabled", requestValidationEnabled);
+            return this;
+        }
+        /**
+         * Allows for bridging the consumer to the Camel routing Error Handler,
+         * which mean any exceptions (if possible) occurred while the Camel
+         * consumer is trying to pickup incoming messages, or the likes, will
+         * now be processed as a message and handled by the routing Error
+         * Handler. Important: This is only possible if the 3rd party component
+         * allows Camel to be alerted if an exception was thrown. Some
+         * components handle this internally only, and therefore
+         * bridgeErrorHandler is not possible. In other situations we may
+         * improve the Camel component to hook into the 3rd party component and
+         * make this possible for future releases. By default the consumer will
+         * use the org.apache.camel.spi.ExceptionHandler to deal with
+         * exceptions, that will be logged at WARN or ERROR level and ignored.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: consumer
+         * 
+         * @param bridgeErrorHandler the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder bridgeErrorHandler(
+                boolean bridgeErrorHandler) {
+            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+            return this;
+        }
+        /**
+         * Name of the Camel component that will service the requests. The
+         * component must be present in Camel registry and it must implement
+         * RestOpenApiConsumerFactory service provider interface. If not set
+         * CLASSPATH is searched for single component that implements
+         * RestOpenApiConsumerFactory SPI. Can be overridden in endpoint
+         * configuration.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param consumerComponentName the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder consumerComponentName(
+                java.lang.String consumerComponentName) {
+            doSetProperty("consumerComponentName", consumerComponentName);
+            return this;
+        }
+        /**
+         * To use a custom strategy for how to process Rest DSL requests.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param restOpenapiProcessorStrategy the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder restOpenapiProcessorStrategy(
+                org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) {
+            doSetProperty("restOpenapiProcessorStrategy", restOpenapiProcessorStrategy);
+            return this;
+        }
         /**
          * API basePath, for example /v2. Default is unset, if set overrides the
          * value present in OpenApi specification.
@@ -110,23 +190,6 @@ public interface RestOpenapiComponentBuilderFactory {
             doSetProperty("lazyStartProducer", lazyStartProducer);
             return this;
         }
-        /**
-         * Enable validation of requests against the configured OpenAPI
-         * specification.
-         * 
-         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
-         * 
-         * Default: false
-         * Group: producer
-         * 
-         * @param requestValidationEnabled the value to set
-         * @return the dsl builder
-         */
-        default RestOpenapiComponentBuilder requestValidationEnabled(
-                boolean requestValidationEnabled) {
-            doSetProperty("requestValidationEnabled", requestValidationEnabled);
-            return this;
-        }
         /**
          * Path to the OpenApi specification file. The scheme, host base path
          * are taken from this specification, but these can be overridden with
@@ -294,10 +357,13 @@ public interface RestOpenapiComponentBuilderFactory {
                 String name,
                 Object value) {
             switch (name) {
+            case "requestValidationEnabled": ((RestOpenApiComponent) component).setRequestValidationEnabled((boolean) value); return true;
+            case "bridgeErrorHandler": ((RestOpenApiComponent) component).setBridgeErrorHandler((boolean) value); return true;
+            case "consumerComponentName": ((RestOpenApiComponent) component).setConsumerComponentName((java.lang.String) value); return true;
+            case "restOpenapiProcessorStrategy": ((RestOpenApiComponent) component).setRestOpenapiProcessorStrategy((org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy) value); return true;
             case "basePath": ((RestOpenApiComponent) component).setBasePath((java.lang.String) value); return true;
             case "host": ((RestOpenApiComponent) component).setHost((java.lang.String) value); return true;
             case "lazyStartProducer": ((RestOpenApiComponent) component).setLazyStartProducer((boolean) value); return true;
-            case "requestValidationEnabled": ((RestOpenApiComponent) component).setRequestValidationEnabled((boolean) value); return true;
             case "specificationUri": ((RestOpenApiComponent) component).setSpecificationUri((java.net.URI) value); return true;
             case "componentName": ((RestOpenApiComponent) component).setComponentName((java.lang.String) value); return true;
             case "consumes": ((RestOpenApiComponent) component).setConsumes((java.lang.String) value); return true;
diff --git a/dsl/camel-componentdsl/src/generated/resources/metadata.json b/dsl/camel-componentdsl/src/generated/resources/metadata.json
index a56bf0307d2..73cf426c947 100644
--- a/dsl/camel-componentdsl/src/generated/resources/metadata.json
+++ b/dsl/camel-componentdsl/src/generated/resources/metadata.json
@@ -6161,7 +6161,7 @@
     "async": false,
     "api": false,
     "consumerOnly": false,
-    "producerOnly": true,
+    "producerOnly": false,
     "lenientProperties": false,
     "remote": true
   },
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
index a0454445e2a..10936800f56 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
@@ -234,6 +234,38 @@ public interface RestOpenApiEndpointBuilderFactory {
             doSetProperty("exchangePattern", exchangePattern);
             return this;
         }
+        /**
+         * To use a custom strategy for how to process Rest DSL requests.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param restOpenapiProcessorStrategy the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder restOpenapiProcessorStrategy(
+                org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) {
+            doSetProperty("restOpenapiProcessorStrategy", restOpenapiProcessorStrategy);
+            return this;
+        }
+        /**
+         * To use a custom strategy for how to process Rest DSL requests.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param restOpenapiProcessorStrategy the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder restOpenapiProcessorStrategy(
+                String restOpenapiProcessorStrategy) {
+            doSetProperty("restOpenapiProcessorStrategy", restOpenapiProcessorStrategy);
+            return this;
+        }
         /**
          * If request validation is enabled, this option provides the capability
          * to customize the creation of OpenApiInteractionValidator used to
diff --git a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
index 6f22f587c84..9827040e0b9 100644
--- a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
+++ b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
@@ -139,6 +139,13 @@ public class RestOpenapiUriDsl(
     it.property("exchangePattern", exchangePattern)
   }
 
+  /**
+   * To use a custom strategy for how to process Rest DSL requests
+   */
+  public fun restOpenapiProcessorStrategy(restOpenapiProcessorStrategy: String) {
+    it.property("restOpenapiProcessorStrategy", restOpenapiProcessorStrategy)
+  }
+
   /**
    * API basePath, for example /v3. Default is unset, if set overrides the value present in OpenApi
    * specification and in the component configuration.


(camel) 27/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 22b59c69ce7475bac5f4bc3435400d52ea95eb5a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 06:32:47 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../src/main/java/org/apache/camel/main/KameletMain.java           | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index 6dd0937661d..477c84a3819 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -766,19 +766,16 @@ public class KameletMain extends MainCommandLineSupport {
         addInitialProperty("camel.component.rest-api.consumerComponentName", "platform-http");
         addInitialProperty("camel.component.rest.consumerComponentName", "platform-http");
         addInitialProperty("camel.component.rest.producerComponentName", "vertx-http");
+        // make it easy to load mock-data from file without having to add camel-mock to classpath
         addInitialProperty("camel.component.rest-openapi.mockIncludePattern", "file:camel-mock/**,classpath:camel-mock/**");
     }
 
     protected String startupInfo() {
         StringBuilder sb = new StringBuilder();
         sb.append("Using Java ").append(System.getProperty("java.version"));
-        String pid = getPid();
-        if (pid != null) {
-            sb.append(" with PID ").append(pid);
-        }
+        sb.append(" with PID ").append(getPid());
         sb.append(". Started by ").append(System.getProperty("user.name"));
         sb.append(" in ").append(System.getProperty("user.dir"));
-
         return sb.toString();
     }
 


(camel) 33/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 36bc449ba76ccdab928ae7f2f9cd09d5f1beb5e3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 13:04:27 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../camel/catalog/components/rest-openapi.json     | 31 ++++++------
 .../camel/catalog/models/restConfiguration.json    |  2 +-
 ...PlatformHttpRestOpenApiConsumerRestDslTest.java | 45 +++++++++++++++++
 .../openapi/RestOpenApiComponentConfigurer.java    |  6 +++
 .../openapi/RestOpenApiEndpointConfigurer.java     |  6 +++
 .../openapi/RestOpenApiEndpointUriFactory.java     |  3 +-
 .../camel/component/rest/openapi/rest-openapi.json | 58 +++++++++++-----------
 .../DefaultRestOpenapiProcessorStrategy.java       | 32 ++++++++++++
 .../rest/openapi/RestOpenApiComponent.java         | 11 ++++
 .../rest/openapi/RestOpenApiEndpoint.java          | 12 ++++-
 .../rest/openapi/RestOpenApiProcessor.java         | 12 ++++-
 .../rest/openapi/RestOpenapiProcessorStrategy.java | 12 +++++
 .../apache/camel/model/rest/restConfiguration.json |  2 +-
 .../apache/camel/model/rest/OpenApiDefinition.java | 19 +++++++
 .../model/rest/RestConfigurationDefinition.java    |  4 +-
 .../apache/camel/model/rest/RestDefinition.java    |  9 ++--
 .../java/org/apache/camel/xml/in/ModelParser.java  |  8 ++-
 .../java/org/apache/camel/xml/out/ModelWriter.java |  1 +
 .../org/apache/camel/yaml/out/ModelWriter.java     |  1 +
 .../dsl/RestOpenApiEndpointBuilderFactory.java     | 15 ++++++
 .../camel/kotlin/components/RestOpenapiUriDsl.kt   |  7 +++
 .../dsl/yaml/deserializers/ModelDeserializers.java |  2 +-
 .../generated/resources/schema/camelYamlDsl.json   |  2 +-
 23 files changed, 243 insertions(+), 57 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index a2f378c6e67..e224a0d248e 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -45,20 +45,21 @@
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
     "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "missingOperation": { "index": 3, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
-    "bridgeErrorHandler": { "index": 4, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
-    "consumerComponentName": { "index": 5, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
-    "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
-    "exchangePattern": { "index": 7, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
-    "mockIncludePattern": { "index": 8, "kind": "parameter", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sep [...]
-    "restOpenapiProcessorStrategy": { "index": 9, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "basePath": { "index": 10, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "consumes": { "index": 11, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
-    "host": { "index": 12, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
-    "produces": { "index": 13, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
-    "componentName": { "index": 14, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
-    "lazyStartProducer": { "index": 15, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
-    "requestValidationCustomizer": { "index": 16, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
-    "requestValidationLevels": { "index": 17, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
+    "apiContextPath": { "index": 3, "kind": "parameter", "displayName": "Api Context Path", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the context-path to use for servicing the OpenAPI specification" },
+    "missingOperation": { "index": 4, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
+    "bridgeErrorHandler": { "index": 5, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
+    "consumerComponentName": { "index": 6, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
+    "exceptionHandler": { "index": 7, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
+    "exchangePattern": { "index": 8, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
+    "mockIncludePattern": { "index": 9, "kind": "parameter", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sep [...]
+    "restOpenapiProcessorStrategy": { "index": 10, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 11, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
+    "consumes": { "index": 12, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
+    "host": { "index": 13, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
+    "produces": { "index": 14, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
+    "componentName": { "index": 15, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
+    "lazyStartProducer": { "index": 16, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "requestValidationCustomizer": { "index": 17, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
+    "requestValidationLevels": { "index": 18, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/restConfiguration.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/restConfiguration.json
index 8f6eabdc526..d72d7945fc5 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/restConfiguration.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/restConfiguration.json
@@ -22,7 +22,7 @@
     "useXForwardHeaders": { "index": 7, "kind": "attribute", "displayName": "Use XForward Headers", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use X-Forward headers to set host etc. for OpenApi. This may be needed in special cases involving reverse-proxy and networking going from HTTP to HTTPS etc. Then the proxy can send X- [...]
     "producerApiDoc": { "index": 8, "kind": "attribute", "displayName": "Producer Api Doc", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the location of the api document the REST producer will use to validate the REST uri and query parameters are valid accordingly to the api document. The location of the api document is loaded from classpath by default, but [...]
     "contextPath": { "index": 9, "kind": "attribute", "displayName": "Context Path", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a leading context-path the REST services will be using. This can be used when using components such as camel-servlet where the deployed web application is deployed using a context-path. Or for components such as camel-jetty or camel-netty [...]
-    "apiContextPath": { "index": 10, "kind": "attribute", "displayName": "Api Context Path", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a leading API context-path the REST API services will be using. This can be used when using components such as camel-servlet where the deployed web application is deployed using a context-path." },
+    "apiContextPath": { "index": 10, "kind": "attribute", "displayName": "Api Context Path", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a leading context-path the REST API will be using. This can be used when using components such as camel-servlet where the deployed web application is deployed using a context-path." },
     "apiContextRouteId": { "index": 11, "kind": "attribute", "displayName": "Api Context Route Id", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the route id to use for the route that services the REST API. The route will by default use an auto assigned route id." },
     "apiVendorExtension": { "index": 12, "kind": "attribute", "displayName": "Api Vendor Extension", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether vendor extension is enabled in the Rest APIs. If enabled then Camel will include additional information as vendor extension (eg keys starting with x-) such as route ids, class names etc [...]
     "hostNameResolver": { "index": 13, "kind": "attribute", "displayName": "Host Name Resolver", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.model.rest.RestHostNameResolver", "enum": [ "allLocalIp", "localHostName", "localIp" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "allLocalIp", "description": "If no hostname has been explicit configured, then this resolver is used to compute the hostname the REST ser [...]
diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
index db51da21007..b836248ab33 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
@@ -16,8 +16,11 @@
  */
 package org.apache.camel.component.platform.http.vertx;
 
+import java.io.FileInputStream;
+
 import org.apache.camel.CamelContext;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.util.IOHelper;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -260,4 +263,46 @@ public class PlatformHttpRestOpenApiConsumerRestDslTest {
         }
     }
 
+    @Test
+    public void testRestOpenApiContextPath() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    rest().openApi()
+                            .specification("openapi-v3.json")
+                            .apiContextPath("api-doc")
+                            .missingOperation("ignore");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .get("/api/v3/pet/123")
+                    .then()
+                    .statusCode(200)
+                    .body(equalTo("{\"pet\": \"tony the tiger\"}"));
+
+            String spec = IOHelper.loadText(new FileInputStream("src/test/resources/openapi-v3.json"));
+
+            given()
+                    .when()
+                    .get("/api/v3/api-doc")
+                    .then()
+                    .statusCode(200)
+                    .contentType("application/json")
+                    .body(equalTo(spec));
+
+        } finally {
+            context.stop();
+        }
+    }
+
 }
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
index ee6d62376fb..5d48898caa9 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
@@ -21,6 +21,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
     public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
         RestOpenApiComponent target = (RestOpenApiComponent) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "apicontextpath":
+        case "apiContextPath": target.setApiContextPath(property(camelContext, java.lang.String.class, value)); return true;
         case "autowiredenabled":
         case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true;
         case "basepath":
@@ -59,6 +61,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "apicontextpath":
+        case "apiContextPath": return java.lang.String.class;
         case "autowiredenabled":
         case "autowiredEnabled": return boolean.class;
         case "basepath":
@@ -98,6 +102,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         RestOpenApiComponent target = (RestOpenApiComponent) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "apicontextpath":
+        case "apiContextPath": return target.getApiContextPath();
         case "autowiredenabled":
         case "autowiredEnabled": return target.isAutowiredEnabled();
         case "basepath":
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
index 93eeebc6306..cdcf0df0cba 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
@@ -21,6 +21,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
     public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
         RestOpenApiEndpoint target = (RestOpenApiEndpoint) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "apicontextpath":
+        case "apiContextPath": target.setApiContextPath(property(camelContext, java.lang.String.class, value)); return true;
         case "basepath":
         case "basePath": target.setBasePath(property(camelContext, java.lang.String.class, value)); return true;
         case "bridgeerrorhandler":
@@ -57,6 +59,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "apicontextpath":
+        case "apiContextPath": return java.lang.String.class;
         case "basepath":
         case "basePath": return java.lang.String.class;
         case "bridgeerrorhandler":
@@ -94,6 +98,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         RestOpenApiEndpoint target = (RestOpenApiEndpoint) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "apicontextpath":
+        case "apiContextPath": return target.getApiContextPath();
         case "basepath":
         case "basePath": return target.getBasePath();
         case "bridgeerrorhandler":
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
index 1f4cda596a6..5831306e28b 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
@@ -21,7 +21,8 @@ public class RestOpenApiEndpointUriFactory extends org.apache.camel.support.comp
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(18);
+        Set<String> props = new HashSet<>(19);
+        props.add("apiContextPath");
         props.add("basePath");
         props.add("bridgeErrorHandler");
         props.add("componentName");
diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index a2f378c6e67..7c83b6b9cb4 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -27,38 +27,40 @@
     "requestValidationEnabled": { "index": 1, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "specificationUri": { "index": 2, "kind": "property", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
     "requestValidationCustomizer": { "index": 3, "kind": "property", "displayName": "Request Validation Customizer", "group": "common (advanced)", "label": "common,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInterac [...]
-    "bridgeErrorHandler": { "index": 4, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
-    "missingOperation": { "index": 5, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
-    "consumerComponentName": { "index": 6, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "mockIncludePattern": { "index": 7, "kind": "property", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sepa [...]
-    "restOpenapiProcessorStrategy": { "index": 8, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "host": { "index": 9, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 10, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fai [...]
-    "componentName": { "index": 11, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
-    "consumes": { "index": 12, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
-    "produces": { "index": 13, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
-    "autowiredEnabled": { "index": 14, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
-    "sslContextParameters": { "index": 15, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
-    "useGlobalSslContextParameters": { "index": 16, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
+    "apiContextPath": { "index": 4, "kind": "property", "displayName": "Api Context Path", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the context-path to use for servicing the OpenAPI specification" },
+    "bridgeErrorHandler": { "index": 5, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
+    "missingOperation": { "index": 6, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
+    "consumerComponentName": { "index": 7, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
+    "mockIncludePattern": { "index": 8, "kind": "property", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sepa [...]
+    "restOpenapiProcessorStrategy": { "index": 9, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "host": { "index": 10, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
+    "lazyStartProducer": { "index": 11, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fai [...]
+    "componentName": { "index": 12, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
+    "consumes": { "index": 13, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
+    "produces": { "index": 14, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
+    "autowiredEnabled": { "index": 15, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
+    "sslContextParameters": { "index": 16, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
+    "useGlobalSslContextParameters": { "index": 17, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
     "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "missingOperation": { "index": 3, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
-    "bridgeErrorHandler": { "index": 4, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
-    "consumerComponentName": { "index": 5, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
-    "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
-    "exchangePattern": { "index": 7, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
-    "mockIncludePattern": { "index": 8, "kind": "parameter", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sep [...]
-    "restOpenapiProcessorStrategy": { "index": 9, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "basePath": { "index": 10, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "consumes": { "index": 11, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
-    "host": { "index": 12, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
-    "produces": { "index": 13, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
-    "componentName": { "index": 14, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
-    "lazyStartProducer": { "index": 15, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
-    "requestValidationCustomizer": { "index": 16, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
-    "requestValidationLevels": { "index": 17, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
+    "apiContextPath": { "index": 3, "kind": "parameter", "displayName": "Api Context Path", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the context-path to use for servicing the OpenAPI specification" },
+    "missingOperation": { "index": 4, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
+    "bridgeErrorHandler": { "index": 5, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
+    "consumerComponentName": { "index": 6, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
+    "exceptionHandler": { "index": 7, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
+    "exchangePattern": { "index": 8, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
+    "mockIncludePattern": { "index": 9, "kind": "parameter", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sep [...]
+    "restOpenapiProcessorStrategy": { "index": 10, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 11, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
+    "consumes": { "index": 12, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
+    "host": { "index": 13, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
+    "produces": { "index": 14, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
+    "componentName": { "index": 15, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
+    "lazyStartProducer": { "index": 16, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "requestValidationCustomizer": { "index": 17, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
+    "requestValidationLevels": { "index": 18, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index 0ac3b7de488..c23cde28873 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.component.rest.openapi;
 
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -61,6 +62,7 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
     private String component = "direct";
     private String missingOperation;
     private String mockIncludePattern;
+    private String apiContextPath;
     private final List<String> uris = new ArrayList<>();
 
     @Override
@@ -137,6 +139,28 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         }
     }
 
+    @Override
+    public boolean processApiSpecification(String specificationUri, Exchange exchange, AsyncCallback callback) {
+        try {
+            Resource res = PluginHelper.getResourceLoader(camelContext).resolveResource(specificationUri);
+            if (res != null && res.exists()) {
+                if (specificationUri.endsWith("json")) {
+                    exchange.getMessage().setHeader(Exchange.CONTENT_TYPE, "application/json");
+                } else if (specificationUri.endsWith("yaml") || specificationUri.endsWith("yml")) {
+                    exchange.getMessage().setHeader(Exchange.CONTENT_TYPE, "text/yaml");
+                }
+                InputStream is = res.getInputStream();
+                String data = IOHelper.loadText(is);
+                exchange.getMessage().setBody(data);
+                IOHelper.close(is);
+            }
+        } catch (Exception e) {
+            exchange.setException(e);
+        }
+        callback.done(true);
+        return true;
+    }
+
     @Override
     public boolean process(Operation operation, String path, Exchange exchange, AsyncCallback callback) {
         if ("mock".equalsIgnoreCase(missingOperation)) {
@@ -256,6 +280,14 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         this.mockIncludePattern = mockIncludePattern;
     }
 
+    public String getApiContextPath() {
+        return apiContextPath;
+    }
+
+    public void setApiContextPath(String apiContextPath) {
+        this.apiContextPath = apiContextPath;
+    }
+
     @Override
     protected void doInit() throws Exception {
         producerCache = new DefaultProducerCache(this, getCamelContext(), 1000);
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index fc69ee65ecf..d9eb5b17925 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -137,6 +137,8 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
                             + " Multiple patterns can be specified separated by comma.",
               label = "consumer,advanced", defaultValue = "classpath:camel-mock/**")
     private String mockIncludePattern = "classpath:camel-mock/**";
+    @Metadata(label = "consumer", description = "Sets the context-path to use for servicing the OpenAPI specification")
+    private String apiContextPath;
     @Metadata(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
     private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
     @Metadata(description = "Enable usage of global SSL context parameters.", label = "security")
@@ -156,6 +158,7 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
     protected Endpoint createEndpoint(final String uri, final String remaining, final Map<String, Object> parameters)
             throws Exception {
         RestOpenApiEndpoint endpoint = new RestOpenApiEndpoint(uri, remaining, this, parameters);
+        endpoint.setApiContextPath(getApiContextPath());
         endpoint.setRequestValidationCustomizer(getRequestValidationCustomizer());
         endpoint.setRequestValidationEnabled(isRequestValidationEnabled());
         endpoint.setRequestValidationLevels(PropertiesHelper.extractProperties(parameters, "validation."));
@@ -227,6 +230,14 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         this.mockIncludePattern = mockIncludePattern;
     }
 
+    public String getApiContextPath() {
+        return apiContextPath;
+    }
+
+    public void setApiContextPath(String apiContextPath) {
+        this.apiContextPath = apiContextPath;
+    }
+
     public void setBasePath(final String basePath) {
         this.basePath = notEmpty(basePath, "basePath");
     }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 0ef9aa3703e..0a29a7c18b5 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -171,6 +171,8 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
                             + " Multiple patterns can be specified separated by comma.",
               label = "consumer,advanced", defaultValue = "classpath:camel-mock/**")
     private String mockIncludePattern;
+    @UriParam(label = "consumer", description = "Sets the context-path to use for servicing the OpenAPI specification")
+    private String apiContextPath;
 
     public RestOpenApiEndpoint() {
         // help tooling instantiate endpoint
@@ -211,7 +213,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     public Consumer createConsumer(final Processor processor) throws Exception {
         OpenAPI doc = loadSpecificationFrom(getCamelContext(), specificationUri);
         String path = determineBasePath(doc);
-        Processor target = new RestOpenApiProcessor(this, doc, path, processor, restOpenapiProcessorStrategy);
+        Processor target = new RestOpenApiProcessor(this, doc, path, apiContextPath, processor, restOpenapiProcessorStrategy);
         CamelContextAware.trySetCamelContext(target, getCamelContext());
         return createConsumerFor(path, target);
     }
@@ -468,6 +470,14 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         return mockIncludePattern;
     }
 
+    public String getApiContextPath() {
+        return apiContextPath;
+    }
+
+    public void setApiContextPath(String apiContextPath) {
+        this.apiContextPath = apiContextPath;
+    }
+
     Producer createProducerFor(
             final OpenAPI openapi, final Operation operation, final String method,
             final String uriTemplate)
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index 429b01dcd4b..44bbbce008d 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -47,14 +47,17 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
     private final RestOpenApiEndpoint endpoint;
     private final OpenAPI openAPI;
     private final String basePath;
+    private final String apiContextPath;
     private final List<RestConsumerContextPathMatcher.ConsumerPath<Operation>> paths = new ArrayList<>();
     private final RestOpenapiProcessorStrategy restOpenapiProcessorStrategy;
 
-    public RestOpenApiProcessor(RestOpenApiEndpoint endpoint, OpenAPI openAPI, String basePath, Processor processor,
-                                RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) {
+    public RestOpenApiProcessor(RestOpenApiEndpoint endpoint, OpenAPI openAPI, String basePath, String apiContextPath,
+                                Processor processor, RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) {
         super(processor);
         this.endpoint = endpoint;
         this.basePath = basePath;
+        // ensure starts with leading slash
+        this.apiContextPath = apiContextPath != null && !apiContextPath.startsWith("/") ? "/" + apiContextPath : apiContextPath;
         this.openAPI = openAPI;
         this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy;
     }
@@ -115,6 +118,11 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
             return restOpenapiProcessorStrategy.process(operation, path, exchange, callback);
         }
 
+        // is it the api-context path
+        if (path != null && path.equals(apiContextPath)) {
+            return restOpenapiProcessorStrategy.processApiSpecification(endpoint.getSpecificationUri(), exchange, callback);
+        }
+
         // okay we cannot process this requires so return either 404 or 405.
         // to know if its 405 then we need to check if any other HTTP method would have a consumer for the "same" request
         final String contextPath = path;
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
index 325e2468cae..5dab95b0a6f 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
@@ -74,4 +74,16 @@ public interface RestOpenapiProcessorStrategy {
      */
     boolean process(Operation operation, String path, Exchange exchange, AsyncCallback callback);
 
+    /**
+     * Strategy for processing the OpenAPI specification (to return the contract)
+     *
+     * @param  exchange the exchange
+     * @param  callback the AsyncCallback will be invoked when the processing of the exchange is completed. If the
+     *                  exchange is completed synchronously, then the callback is also invoked synchronously. The
+     *                  callback should therefore be careful of starting recursive loop.
+     * @return          (doneSync) true to continue execute synchronously, false to continue being executed
+     *                  asynchronously
+     */
+    boolean processApiSpecification(String specificationUri, Exchange exchange, AsyncCallback callback);
+
 }
diff --git a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/restConfiguration.json b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/restConfiguration.json
index 8f6eabdc526..d72d7945fc5 100644
--- a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/restConfiguration.json
+++ b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/restConfiguration.json
@@ -22,7 +22,7 @@
     "useXForwardHeaders": { "index": 7, "kind": "attribute", "displayName": "Use XForward Headers", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use X-Forward headers to set host etc. for OpenApi. This may be needed in special cases involving reverse-proxy and networking going from HTTP to HTTPS etc. Then the proxy can send X- [...]
     "producerApiDoc": { "index": 8, "kind": "attribute", "displayName": "Producer Api Doc", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the location of the api document the REST producer will use to validate the REST uri and query parameters are valid accordingly to the api document. The location of the api document is loaded from classpath by default, but [...]
     "contextPath": { "index": 9, "kind": "attribute", "displayName": "Context Path", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a leading context-path the REST services will be using. This can be used when using components such as camel-servlet where the deployed web application is deployed using a context-path. Or for components such as camel-jetty or camel-netty [...]
-    "apiContextPath": { "index": 10, "kind": "attribute", "displayName": "Api Context Path", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a leading API context-path the REST API services will be using. This can be used when using components such as camel-servlet where the deployed web application is deployed using a context-path." },
+    "apiContextPath": { "index": 10, "kind": "attribute", "displayName": "Api Context Path", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a leading context-path the REST API will be using. This can be used when using components such as camel-servlet where the deployed web application is deployed using a context-path." },
     "apiContextRouteId": { "index": 11, "kind": "attribute", "displayName": "Api Context Route Id", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the route id to use for the route that services the REST API. The route will by default use an auto assigned route id." },
     "apiVendorExtension": { "index": 12, "kind": "attribute", "displayName": "Api Vendor Extension", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether vendor extension is enabled in the Rest APIs. If enabled then Camel will include additional information as vendor extension (eg keys starting with x-) such as route ids, class names etc [...]
     "hostNameResolver": { "index": 13, "kind": "attribute", "displayName": "Host Name Resolver", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.model.rest.RestHostNameResolver", "enum": [ "allLocalIp", "localHostName", "localIp" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "allLocalIp", "description": "If no hostname has been explicit configured, then this resolver is used to compute the hostname the REST ser [...]
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
index 1eefdff7728..91183e54fee 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
@@ -38,6 +38,8 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
 
     @XmlAttribute(required = true)
     private String specification;
+    @Metadata
+    private String apiContextPath;
     @XmlAttribute
     private String routeId;
     @XmlAttribute
@@ -72,6 +74,14 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
         this.specification = specification;
     }
 
+    public String getApiContextPath() {
+        return apiContextPath;
+    }
+
+    public void setApiContextPath(String apiContextPath) {
+        this.apiContextPath = apiContextPath;
+    }
+
     public String getDisabled() {
         return disabled;
     }
@@ -129,6 +139,15 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
         return this;
     }
 
+    /**
+     * Whether to enable api-doc that exposes the OpenAPI specification file as a REST endpoint.
+     * This allows clients to obtain the specification from the running Camel application.
+     */
+    public OpenApiDefinition apiContextPath(String apiDoc) {
+        this.apiContextPath = apiDoc;
+        return this;
+    }
+
     /**
      * Whether to disable the OpenAPI entirely. Once the OpenAPI has been disabled then it cannot be
      * enabled later at runtime.
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
index 245b339de23..d770f6cae1a 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
@@ -249,7 +249,7 @@ public class RestConfigurationDefinition {
     }
 
     /**
-     * Sets a leading API context-path the REST API services will be using.
+     * Sets a leading context-path the REST API will be using.
      * <p/>
      * This can be used when using components such as <tt>camel-servlet</tt> where the deployed web application is
      * deployed using a context-path.
@@ -582,7 +582,7 @@ public class RestConfigurationDefinition {
     }
 
     /**
-     * Sets a leading context-path the REST services will be using.
+     * Sets a leading context-path the REST API will be using.
      * <p/>
      * This can be used when using components such as <tt>camel-servlet</tt> where the deployed web application is
      * deployed using a context-path. Or for components such as <tt>camel-jetty</tt> or <tt>camel-netty-http</tt> that
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
index 6f1406b8caf..f5d30621789 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
@@ -868,7 +868,7 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
             addRouteDefinition(camelContext, filter, answer, config.getComponent(), config.getProducerComponent());
         }
         if (openApi != null) {
-            addRouteDefinition(camelContext, openApi, answer, config.getComponent(), config.getProducerComponent());
+            addRouteDefinition(camelContext, openApi, answer, config.getComponent(), config.getProducerComponent(), config.getApiContextPath());
         }
 
         return answer;
@@ -969,7 +969,7 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
     @SuppressWarnings("rawtypes")
     private void addRouteDefinition(
             CamelContext camelContext, OpenApiDefinition openApi, List<RouteDefinition> answer,
-            String component, String producerComponent) {
+            String component, String producerComponent, String apiContextPath) {
 
         RouteDefinition route = new RouteDefinition();
         if (openApi.getRouteId() != null) {
@@ -1013,7 +1013,7 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
         if (producerComponent != null && !producerComponent.isEmpty()) {
             options.put("producerComponentName", producerComponent);
         }
-        Boolean validate = parseBoolean(camelContext, getClientRequestValidation());
+        Boolean validate = parseBoolean(camelContext, getClientRequestValidation()); // TODO: move this to open-api so its all the same place
         if (validate != null && validate) {
             options.put("requestValidationEnabled", "true");
         }
@@ -1023,6 +1023,9 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
         if (openApi.getMockIncludePattern() != null) {
             options.put("mockIncludePattern", openApi.getMockIncludePattern());
         }
+        if (openApi.getApiContextPath() != null) {
+            options.put("apiContextPath", openApi.getApiContextPath());
+        }
 
         // include optional description
         String description = openApi.getDescription();
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index 3d97bfcbcbb..aaefc3d2747 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -3310,7 +3310,13 @@ public class ModelParser extends BaseParser {
                 default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
             }
             return true;
-        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+        }, (def, key) -> {
+            if ("apiContextPath".equals(key)) {
+                def.setApiContextPath(doParseText());
+                return true;
+            }
+            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+        }, noValueHandler());
     }
     protected OpenIdConnectDefinition doParseOpenIdConnectDefinition() throws IOException, XmlPullParserException {
         return doParse(new OpenIdConnectDefinition(), (def, key, val) -> {
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index c889b477c4f..b2d94894bf5 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -4424,6 +4424,7 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("routeId", def.getRouteId());
         doWriteAttribute("specification", def.getSpecification());
         doWriteAttribute("disabled", def.getDisabled());
+        doWriteElement("apiContextPath", def.getApiContextPath(), this::doWriteString);
         endElement(name);
     }
     protected void doWriteOpenIdConnectDefinition(
diff --git a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index 4630515246d..eecb2246f2d 100644
--- a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++ b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -4424,6 +4424,7 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("routeId", def.getRouteId());
         doWriteAttribute("specification", def.getSpecification());
         doWriteAttribute("disabled", def.getDisabled());
+        doWriteElement("apiContextPath", def.getApiContextPath(), this::doWriteString);
         endElement(name);
     }
     protected void doWriteOpenIdConnectDefinition(
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
index e53f317f27b..64f42d8e8d1 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
@@ -79,6 +79,21 @@ public interface RestOpenApiEndpointBuilderFactory {
             doSetProperty("requestValidationEnabled", requestValidationEnabled);
             return this;
         }
+        /**
+         * Sets the context-path to use for servicing the OpenAPI specification.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: consumer
+         * 
+         * @param apiContextPath the value to set
+         * @return the dsl builder
+         */
+        default RestOpenApiEndpointConsumerBuilder apiContextPath(
+                String apiContextPath) {
+            doSetProperty("apiContextPath", apiContextPath);
+            return this;
+        }
         /**
          * Whether the consumer should fail,ignore or return a mock response for
          * OpenAPI operations that are not mapped to a corresponding route.
diff --git a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
index 038f1cc4836..74e3bbd5f5c 100644
--- a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
+++ b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
@@ -83,6 +83,13 @@ public class RestOpenapiUriDsl(
     it.property("requestValidationEnabled", requestValidationEnabled.toString())
   }
 
+  /**
+   * Sets the context-path to use for servicing the OpenAPI specification
+   */
+  public fun apiContextPath(apiContextPath: String) {
+    it.property("apiContextPath", apiContextPath)
+  }
+
   /**
    * Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that
    * are not mapped to a corresponding route.
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index 3aaddb6953b..53d3374a1d2 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -13875,7 +13875,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
             deprecated = false,
             properties = {
                     @YamlProperty(name = "apiComponent", type = "enum:openapi,swagger", description = "The name of the Camel component to use as the REST API. If no API Component has been explicit configured, then Camel will lookup if there is a Camel component responsible for servicing and generating the REST API documentation, or if a org.apache.camel.spi.RestApiProcessorFactory is registered in the registry. If either one is found, then that is being used.", displayName = "Api Component"),
-                    @YamlProperty(name = "apiContextPath", type = "string", description = "Sets a leading API context-path the REST API services will be using. This can be used when using components such as camel-servlet where the deployed web application is deployed using a context-path.", displayName = "Api Context Path"),
+                    @YamlProperty(name = "apiContextPath", type = "string", description = "Sets a leading context-path the REST API will be using. This can be used when using components such as camel-servlet where the deployed web application is deployed using a context-path.", displayName = "Api Context Path"),
                     @YamlProperty(name = "apiContextRouteId", type = "string", description = "Sets the route id to use for the route that services the REST API. The route will by default use an auto assigned route id.", displayName = "Api Context Route Id"),
                     @YamlProperty(name = "apiHost", type = "string", description = "To use a specific hostname for the API documentation (such as swagger or openapi) This can be used to override the generated host with this configured hostname", displayName = "Api Host"),
                     @YamlProperty(name = "apiProperty", type = "array:org.apache.camel.model.rest.RestPropertyDefinition", description = "Allows to configure as many additional properties for the api documentation. For example set property api.title to my cool stuff", displayName = "Api Property"),
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index 06660fe71d7..e03199e5b61 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -15336,7 +15336,7 @@
           "apiContextPath" : {
             "type" : "string",
             "title" : "Api Context Path",
-            "description" : "Sets a leading API context-path the REST API services will be using. This can be used when using components such as camel-servlet where the deployed web application is deployed using a context-path."
+            "description" : "Sets a leading context-path the REST API will be using. This can be used when using components such as camel-servlet where the deployed web application is deployed using a context-path."
           },
           "apiContextRouteId" : {
             "type" : "string",


(camel) 21/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f7d730b5d54d54e129069ea1c345f133c74f71c8
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 16:58:34 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../vertx/PlatformHttpRestOpenApiConsumerTest.java | 32 ++++++++++
 .../src/test/resources/camel-mock/pet/444.json     |  3 +
 .../openapi/RestOpenApiComponentConfigurer.java    |  6 ++
 .../openapi/RestOpenApiEndpointConfigurer.java     |  6 ++
 .../openapi/RestOpenApiEndpointUriFactory.java     |  3 +-
 .../camel/component/rest/openapi/rest-openapi.json | 38 +++++------
 .../DefaultRestOpenapiProcessorStrategy.java       | 74 ++++++++++++++++++++--
 .../rest/openapi/RestOpenApiComponent.java         | 17 ++++-
 .../rest/openapi/RestOpenApiEndpoint.java          | 12 ++++
 .../rest/openapi/RestOpenApiProcessor.java         |  1 +
 .../rest/openapi/RestOpenapiProcessorStrategy.java | 12 ++++
 11 files changed, 179 insertions(+), 25 deletions(-)

diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
index 57acb01609d..e67426764f1 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
@@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test;
 
 import static io.restassured.RestAssured.given;
 import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.equalToCompressingWhiteSpace;
 import static org.junit.jupiter.api.Assertions.fail;
 
 public class PlatformHttpRestOpenApiConsumerTest {
@@ -235,4 +236,35 @@ public class PlatformHttpRestOpenApiConsumerTest {
         }
     }
 
+    @Test
+    public void testRestOpenApiMockData() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("rest-openapi:classpath:openapi-v3.json?missingOperation=mock")
+                            .log("dummy");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .contentType("application/json")
+                    .get("/api/v3/pet/444")
+                    .then()
+                    .statusCode(200)
+                    .body(equalToCompressingWhiteSpace(
+                            """
+                                    {
+                                      "pet": "donald the dock"
+                                    }"""));
+        } finally {
+            context.stop();
+        }
+    }
+
 }
diff --git a/components/camel-platform-http-vertx/src/test/resources/camel-mock/pet/444.json b/components/camel-platform-http-vertx/src/test/resources/camel-mock/pet/444.json
new file mode 100644
index 00000000000..9c7739d6022
--- /dev/null
+++ b/components/camel-platform-http-vertx/src/test/resources/camel-mock/pet/444.json
@@ -0,0 +1,3 @@
+{
+  "pet": "donald the dock"
+}
\ No newline at end of file
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
index ae6772faf9a..ee6d62376fb 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
@@ -37,6 +37,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
         case "missingoperation":
         case "missingOperation": target.setMissingOperation(property(camelContext, java.lang.String.class, value)); return true;
+        case "mockincludepattern":
+        case "mockIncludePattern": target.setMockIncludePattern(property(camelContext, java.lang.String.class, value)); return true;
         case "produces": target.setProduces(property(camelContext, java.lang.String.class, value)); return true;
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": target.setRequestValidationCustomizer(property(camelContext, org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer.class, value)); return true;
@@ -73,6 +75,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "lazyStartProducer": return boolean.class;
         case "missingoperation":
         case "missingOperation": return java.lang.String.class;
+        case "mockincludepattern":
+        case "mockIncludePattern": return java.lang.String.class;
         case "produces": return java.lang.String.class;
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": return org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer.class;
@@ -110,6 +114,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "lazyStartProducer": return target.isLazyStartProducer();
         case "missingoperation":
         case "missingOperation": return target.getMissingOperation();
+        case "mockincludepattern":
+        case "mockIncludePattern": return target.getMockIncludePattern();
         case "produces": return target.getProduces();
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": return target.getRequestValidationCustomizer();
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
index 6766a773f15..93eeebc6306 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
@@ -39,6 +39,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
         case "missingoperation":
         case "missingOperation": target.setMissingOperation(property(camelContext, java.lang.String.class, value)); return true;
+        case "mockincludepattern":
+        case "mockIncludePattern": target.setMockIncludePattern(property(camelContext, java.lang.String.class, value)); return true;
         case "produces": target.setProduces(property(camelContext, java.lang.String.class, value)); return true;
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": target.setRequestValidationCustomizer(property(camelContext, org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer.class, value)); return true;
@@ -73,6 +75,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         case "lazyStartProducer": return boolean.class;
         case "missingoperation":
         case "missingOperation": return java.lang.String.class;
+        case "mockincludepattern":
+        case "mockIncludePattern": return java.lang.String.class;
         case "produces": return java.lang.String.class;
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": return org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer.class;
@@ -108,6 +112,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         case "lazyStartProducer": return target.isLazyStartProducer();
         case "missingoperation":
         case "missingOperation": return target.getMissingOperation();
+        case "mockincludepattern":
+        case "mockIncludePattern": return target.getMockIncludePattern();
         case "produces": return target.getProduces();
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": return target.getRequestValidationCustomizer();
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
index f841c7ad9af..1f4cda596a6 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
@@ -21,7 +21,7 @@ public class RestOpenApiEndpointUriFactory extends org.apache.camel.support.comp
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(17);
+        Set<String> props = new HashSet<>(18);
         props.add("basePath");
         props.add("bridgeErrorHandler");
         props.add("componentName");
@@ -32,6 +32,7 @@ public class RestOpenApiEndpointUriFactory extends org.apache.camel.support.comp
         props.add("host");
         props.add("lazyStartProducer");
         props.add("missingOperation");
+        props.add("mockIncludePattern");
         props.add("operationId");
         props.add("produces");
         props.add("requestValidationCustomizer");
diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index e4b0b0ac3fb..aefaf840aac 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -30,15 +30,16 @@
     "bridgeErrorHandler": { "index": 4, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
     "missingOperation": { "index": 5, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
     "consumerComponentName": { "index": 6, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "restOpenapiProcessorStrategy": { "index": 7, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "host": { "index": 8, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 9, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "componentName": { "index": 10, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
-    "consumes": { "index": 11, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
-    "produces": { "index": 12, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
-    "autowiredEnabled": { "index": 13, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
-    "sslContextParameters": { "index": 14, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
-    "useGlobalSslContextParameters": { "index": 15, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
+    "mockIncludePattern": { "index": 7, "kind": "property", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/*", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separ [...]
+    "restOpenapiProcessorStrategy": { "index": 8, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "host": { "index": 9, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 10, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fai [...]
+    "componentName": { "index": 11, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
+    "consumes": { "index": 12, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
+    "produces": { "index": 13, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
+    "autowiredEnabled": { "index": 14, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
+    "sslContextParameters": { "index": 15, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
+    "useGlobalSslContextParameters": { "index": 16, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
@@ -49,14 +50,15 @@
     "consumerComponentName": { "index": 5, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
     "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
     "exchangePattern": { "index": 7, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
-    "restOpenapiProcessorStrategy": { "index": 8, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "basePath": { "index": 9, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "consumes": { "index": 10, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
-    "host": { "index": 11, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
-    "produces": { "index": 12, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
-    "componentName": { "index": 13, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
-    "lazyStartProducer": { "index": 14, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
-    "requestValidationCustomizer": { "index": 15, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
-    "requestValidationLevels": { "index": 16, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
+    "mockIncludePattern": { "index": 8, "kind": "parameter", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/*", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sepa [...]
+    "restOpenapiProcessorStrategy": { "index": 9, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 10, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
+    "consumes": { "index": 11, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
+    "host": { "index": 12, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
+    "produces": { "index": 13, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
+    "componentName": { "index": 14, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
+    "lazyStartProducer": { "index": 15, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "requestValidationCustomizer": { "index": 16, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
+    "requestValidationLevels": { "index": 17, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index 40709fb260a..bd873724294 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.rest.openapi;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -30,10 +31,17 @@ import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
 import org.apache.camel.NonManagedService;
 import org.apache.camel.Route;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.PackageScanResourceResolver;
 import org.apache.camel.spi.ProducerCache;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.support.ExchangeHelper;
+import org.apache.camel.support.PluginHelper;
 import org.apache.camel.support.cache.DefaultProducerCache;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.IOHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -49,6 +57,7 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
     private ProducerCache producerCache;
     private String component = "direct";
     private String missingOperation;
+    private String mockIncludePattern;
 
     @Override
     public void validateOpenApi(OpenAPI openAPI) throws Exception {
@@ -94,10 +103,7 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
             // check if there is a route
             Endpoint e = camelContext.hasEndpoint(component + ":" + operation.getOperationId());
             if (e == null) {
-                // no route for the given operation, so lets return an empty response
-                exchange.getMessage().setBody("");
-                // TODO: load canned response from classpath if exist
-                exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 204);
+                loadMockData(operation, path, exchange);
                 callback.done(true);
                 return true;
             }
@@ -114,6 +120,56 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         });
     }
 
+    private void loadMockData(Operation operation, String path, Exchange exchange) {
+        final PackageScanResourceResolver resolver = PluginHelper.getPackageScanResourceResolver(camelContext);
+        final String[] includes = mockIncludePattern != null ? mockIncludePattern.split(",") : null;
+
+        Collection<Resource> accepted = new ArrayList<>();
+        for (String include : includes) {
+            try {
+                for (Resource resource : resolver.findResources(include)) {
+                    accepted.add(resource);
+                }
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeException(e);
+            }
+        }
+
+        boolean json = false;
+        boolean xml = false;
+        String ct = ExchangeHelper.getContentType(exchange);
+        if (ct != null) {
+            json = ct.contains("json");
+            xml = ct.contains("xml");
+        }
+
+        Resource found = null;
+        for (Resource resource : accepted) {
+            String target = FileUtil.stripFirstLeadingSeparator(path);
+            String loc = FileUtil.stripExt(FileUtil.compactPath(resource.getLocation(), '/'));
+            String onlyExt = FileUtil.onlyExt(resource.getLocation());
+            boolean match = loc.endsWith(target);
+            boolean matchExt = !json && !xml || json && onlyExt.equals("json") || xml && onlyExt.equals("xml");
+            if (match && matchExt) {
+                found = resource;
+                break;
+            }
+        }
+        if (found != null) {
+            try {
+                // use the mock data as response
+                exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 200);
+                exchange.getMessage().setBody(IOHelper.loadText(found.getInputStream()));
+            } catch (Exception e) {
+                // ignore
+            }
+        } else {
+            // no mock data, so return an empty response
+            exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 204);
+            exchange.getMessage().setBody("");
+        }
+    }
+
     @Override
     public CamelContext getCamelContext() {
         return camelContext;
@@ -143,6 +199,16 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         this.missingOperation = missingOperation;
     }
 
+    @Override
+    public String getMockIncludePattern() {
+        return mockIncludePattern;
+    }
+
+    @Override
+    public void setMockIncludePattern(String mockIncludePattern) {
+        this.mockIncludePattern = mockIncludePattern;
+    }
+
     @Override
     protected void doInit() throws Exception {
         producerCache = new DefaultProducerCache(this, getCamelContext(), 1000);
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index 05858566d23..cefe8244e4a 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -47,7 +47,7 @@ import static org.apache.camel.util.StringHelper.notEmpty;
  * <pre>
  * from(...).to("rest-openapi:https://petstore3.swagger.io/api/v3/openapi.json#getPetById")
  * </pre>
- *
+ * <p>
  * This relies on only one {@link RestProducerFactory} component being available to Camel, you can use specific, for
  * instance preconfigured component by using the {@code componentName} endpoint property. For example using Undertow
  * component in Java DSL:
@@ -61,7 +61,7 @@ import static org.apache.camel.util.StringHelper.notEmpty;
  *
  * from(...).to("rest-openapi:https://petstore3.swagger.io/api/v3/openapi.json#getPetById?componentName=myUndertow")
  * </pre>
- *
+ * <p>
  * The most concise way of using this component would be to define it in the Camel context under a meaningful name, for
  * example:
  *
@@ -133,6 +133,10 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
     @Metadata(description = "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.",
               label = "consumer", enums = "fail,ignore,mock", defaultValue = "fail")
     private String missingOperation;
+    @Metadata(description = "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern."
+                            + " Multiple patterns can be specified separated by comma.",
+              label = "consumer,advanced", defaultValue = "classpath:camel-mock/*")
+    private String mockIncludePattern = "classpath:camel-mock/*";
     @Metadata(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
     private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
     @Metadata(description = "Enable usage of global SSL context parameters.", label = "security")
@@ -157,6 +161,7 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         endpoint.setRequestValidationLevels(PropertiesHelper.extractProperties(parameters, "validation."));
         endpoint.setRestOpenapiProcessorStrategy(getRestOpenapiProcessorStrategy());
         endpoint.setMissingOperation(getMissingOperation());
+        endpoint.setMockIncludePattern(getMockIncludePattern());
         setProperties(endpoint, parameters);
         return endpoint;
     }
@@ -214,6 +219,14 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         this.missingOperation = missingOperation;
     }
 
+    public String getMockIncludePattern() {
+        return mockIncludePattern;
+    }
+
+    public void setMockIncludePattern(String mockIncludePattern) {
+        this.mockIncludePattern = mockIncludePattern;
+    }
+
     public void setBasePath(final String basePath) {
         this.basePath = notEmpty(basePath, "basePath");
     }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 90cf95b83b5..8852e838f1b 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -169,6 +169,10 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     @UriParam(description = "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.",
               enums = "fail,ignore,mock", label = "consumer", defaultValue = "fail")
     private String missingOperation;
+    @UriParam(description = "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern."
+                            + " Multiple patterns can be specified separated by comma.",
+              label = "consumer,advanced", defaultValue = "classpath:camel-mock/*")
+    private String mockIncludePattern;
 
     public RestOpenApiEndpoint() {
         // help tooling instantiate endpoint
@@ -458,6 +462,14 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         this.missingOperation = missingOperation;
     }
 
+    public void setMockIncludePattern(String mockIncludePattern) {
+        this.mockIncludePattern = mockIncludePattern;
+    }
+
+    public String getMockIncludePattern() {
+        return mockIncludePattern;
+    }
+
     Producer createProducerFor(
             final OpenAPI openapi, final Operation operation, final String method,
             final String uriTemplate)
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index d7a6c0e50fa..35aa33035f2 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -158,6 +158,7 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
         super.doInit();
 
         restOpenapiProcessorStrategy.setMissingOperation(endpoint.getMissingOperation());
+        restOpenapiProcessorStrategy.setMockIncludePattern(endpoint.getMockIncludePattern());
         ServiceHelper.initService(restOpenapiProcessorStrategy);
 
         // validate openapi contract
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
index dcb1938dae2..325e2468cae 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
@@ -38,6 +38,18 @@ public interface RestOpenapiProcessorStrategy {
      */
     String getMissingOperation();
 
+    /**
+     * Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple
+     * patterns can be specified separated by comma.
+     */
+    void setMockIncludePattern(String mockIncludePattern);
+
+    /**
+     * Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple
+     * patterns can be specified separated by comma.
+     */
+    String getMockIncludePattern();
+
     /**
      * Validates the OpenAPI specification on startup
      *


(camel) 19/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f76aaf6825e9e7b9fe5c588d4dd4198cfe1a32d9
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 14:18:14 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../camel/catalog/components/rest-openapi.json     | 30 +++++------
 .../openapi/RestOpenApiComponentConfigurer.java    |  4 +-
 .../camel/component/rest/openapi/rest-openapi.json | 30 +++++------
 .../src/main/docs/rest-openapi-component.adoc      |  2 +-
 .../rest/openapi/RestOpenApiComponent.java         | 44 ++++++++--------
 .../rest/openapi/RestOpenApiEndpoint.java          | 60 +++++++++-------------
 .../camel/component/rest/openapi/HttpsV3Test.java  |  3 +-
 .../rest/openapi/RestOpenApiComponentV3Test.java   |  6 ++-
 .../openapi/RestOpenApiComponentV3YamlTest.java    |  7 +--
 .../RestOpenApiCustomValidatorCustomizerTest.java  |  3 +-
 .../rest/openapi/RestOpenApiEndpointV3Test.java    |  8 ++-
 .../openapi/RestOpenApiRequestValidationTest.java  |  3 +-
 .../ROOT/pages/camel-4x-upgrade-guide-4_6.adoc     |  6 +++
 .../dsl/RestOpenapiComponentBuilderFactory.java    |  6 +--
 14 files changed, 99 insertions(+), 113 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index d6b3784e2d9..e4b0b0ac3fb 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -23,25 +23,25 @@
     "remote": true
   },
   "componentProperties": {
-    "requestValidationEnabled": { "index": 0, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
-    "missingOperation": { "index": 2, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
-    "consumerComponentName": { "index": 3, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "restOpenapiProcessorStrategy": { "index": 4, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "basePath": { "index": 5, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
-    "host": { "index": 6, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 7, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "specificationUri": { "index": 8, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
-    "componentName": { "index": 9, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
-    "consumes": { "index": 10, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
-    "produces": { "index": 11, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
-    "autowiredEnabled": { "index": 12, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
-    "requestValidationCustomizer": { "index": 13, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
+    "basePath": { "index": 0, "kind": "property", "displayName": "Base Path", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
+    "requestValidationEnabled": { "index": 1, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
+    "specificationUri": { "index": 2, "kind": "property", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
+    "requestValidationCustomizer": { "index": 3, "kind": "property", "displayName": "Request Validation Customizer", "group": "common (advanced)", "label": "common,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInterac [...]
+    "bridgeErrorHandler": { "index": 4, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
+    "missingOperation": { "index": 5, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
+    "consumerComponentName": { "index": 6, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
+    "restOpenapiProcessorStrategy": { "index": 7, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "host": { "index": 8, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 9, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "componentName": { "index": 10, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
+    "consumes": { "index": 11, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
+    "produces": { "index": 12, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
+    "autowiredEnabled": { "index": 13, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
     "sslContextParameters": { "index": 14, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
     "useGlobalSslContextParameters": { "index": 15, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
-    "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not give [...]
+    "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
     "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "missingOperation": { "index": 3, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
index 96dd8f657ec..ae6772faf9a 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
@@ -45,7 +45,7 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "restopenapiprocessorstrategy":
         case "restOpenapiProcessorStrategy": target.setRestOpenapiProcessorStrategy(property(camelContext, org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy.class, value)); return true;
         case "specificationuri":
-        case "specificationUri": target.setSpecificationUri(property(camelContext, java.net.URI.class, value)); return true;
+        case "specificationUri": target.setSpecificationUri(property(camelContext, java.lang.String.class, value)); return true;
         case "sslcontextparameters":
         case "sslContextParameters": target.setSslContextParameters(property(camelContext, org.apache.camel.support.jsse.SSLContextParameters.class, value)); return true;
         case "useglobalsslcontextparameters":
@@ -81,7 +81,7 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "restopenapiprocessorstrategy":
         case "restOpenapiProcessorStrategy": return org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy.class;
         case "specificationuri":
-        case "specificationUri": return java.net.URI.class;
+        case "specificationUri": return java.lang.String.class;
         case "sslcontextparameters":
         case "sslContextParameters": return org.apache.camel.support.jsse.SSLContextParameters.class;
         case "useglobalsslcontextparameters":
diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index d6b3784e2d9..e4b0b0ac3fb 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -23,25 +23,25 @@
     "remote": true
   },
   "componentProperties": {
-    "requestValidationEnabled": { "index": 0, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
-    "missingOperation": { "index": 2, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
-    "consumerComponentName": { "index": 3, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "restOpenapiProcessorStrategy": { "index": 4, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "basePath": { "index": 5, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
-    "host": { "index": 6, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 7, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "specificationUri": { "index": 8, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
-    "componentName": { "index": 9, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
-    "consumes": { "index": 10, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
-    "produces": { "index": 11, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
-    "autowiredEnabled": { "index": 12, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
-    "requestValidationCustomizer": { "index": 13, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
+    "basePath": { "index": 0, "kind": "property", "displayName": "Base Path", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
+    "requestValidationEnabled": { "index": 1, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
+    "specificationUri": { "index": 2, "kind": "property", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
+    "requestValidationCustomizer": { "index": 3, "kind": "property", "displayName": "Request Validation Customizer", "group": "common (advanced)", "label": "common,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInterac [...]
+    "bridgeErrorHandler": { "index": 4, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
+    "missingOperation": { "index": 5, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
+    "consumerComponentName": { "index": 6, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
+    "restOpenapiProcessorStrategy": { "index": 7, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "host": { "index": 8, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 9, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "componentName": { "index": 10, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
+    "consumes": { "index": 11, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
+    "produces": { "index": 12, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
+    "autowiredEnabled": { "index": 13, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
     "sslContextParameters": { "index": 14, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
     "useGlobalSslContextParameters": { "index": 15, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
-    "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not give [...]
+    "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
     "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "missingOperation": { "index": 3, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
diff --git a/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc b/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc
index e521f8767d0..f650a421368 100644
--- a/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc
+++ b/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc
@@ -147,7 +147,7 @@ Start by defining a _RestOpenApiComponent_ bean:
 @Bean
 public Component petstore(CamelContext camelContext) {
     RestOpenApiComponent petstore = new RestOpenApiComponent(camelContext);
-    petstore.setSpecificationUri(new URI("https://petstore3.swagger.io/api/v3/openapi.json"));
+    petstore.setSpecificationUri("https://petstore3.swagger.io/api/v3/openapi.json");
     petstore.setHost("https://petstore3.swagger.io");
     return petstore;
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index 07dfb4556f1..05858566d23 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.component.rest.openapi;
 
-import java.net.URI;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
@@ -33,7 +32,6 @@ import org.apache.camel.util.PropertiesHelper;
 
 import static org.apache.camel.component.rest.openapi.RestOpenApiHelper.isHostParam;
 import static org.apache.camel.component.rest.openapi.RestOpenApiHelper.isMediaRange;
-import static org.apache.camel.util.ObjectHelper.notNull;
 import static org.apache.camel.util.StringHelper.notEmpty;
 
 /**
@@ -82,12 +80,18 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
 
     public static final String DEFAULT_BASE_PATH = "/";
 
-    static final URI DEFAULT_SPECIFICATION_URI = URI.create(RestOpenApiComponent.DEFAULT_SPECIFICATION_URI_STR);
-
-    static final String DEFAULT_SPECIFICATION_URI_STR = "openapi.json";
+    static final String DEFAULT_SPECIFICATION_URI = "openapi.json";
 
+    @Metadata(description = "Path to the OpenApi specification file. The scheme, host base path are taken from this"
+                            + " specification, but these can be overridden with properties on the component or endpoint level. If not"
+                            + " given the component tries to load `openapi.json` resource. Note that the `host` defined on the"
+                            + " component and endpoint of this Component should contain the scheme, hostname and optionally the"
+                            + " port in the URI syntax (i.e. `https://api.example.com:8080`). Can be overridden in endpoint"
+                            + " configuration.",
+              defaultValue = DEFAULT_SPECIFICATION_URI, label = "common")
+    private String specificationUri;
     @Metadata(description = "API basePath, for example \"`/v2`\". Default is unset, if set overrides the value present in OpenApi specification.",
-              label = "producer")
+              label = "common")
     private String basePath = "";
     @Metadata(description = "Name of the Camel component that will perform the requests. The component must be present"
                             + " in Camel registry and it must implement RestProducerFactory service provider interface. If not set"
@@ -120,30 +124,22 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
                             + " any value present in the OpenApi specification. Can be overridden in endpoint configuration.",
               label = "producer,advanced")
     private String produces;
-    @Metadata(description = "Path to the OpenApi specification file. The scheme, host base path are taken from this"
-                            + " specification, but these can be overridden with properties on the component or endpoint level. If not"
-                            + " given the component tries to load `openapi.json` resource. Note that the `host` defined on the"
-                            + " component and endpoint of this Component should contain the scheme, hostname and optionally the"
-                            + " port in the URI syntax (i.e. `https://api.example.com:8080`). Can be overridden in endpoint"
-                            + " configuration.",
-              defaultValue = DEFAULT_SPECIFICATION_URI_STR, label = "producer")
-    private URI specificationUri;
-    @Metadata(description = "Enable validation of requests against the configured OpenAPI specification")
+    @Metadata(label = "common", description = "Enable validation of requests against the configured OpenAPI specification")
     private boolean requestValidationEnabled;
     @Metadata(description = "If request validation is enabled, this option provides the capability to customize"
                             + " the creation of OpenApiInteractionValidator used to validate requests.",
-              label = "advanced")
+              label = "common,advanced")
     private RequestValidationCustomizer requestValidationCustomizer = new DefaultRequestValidationCustomizer();
+    @Metadata(description = "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.",
+              label = "consumer", enums = "fail,ignore,mock", defaultValue = "fail")
+    private String missingOperation;
+    @Metadata(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
+    private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
     @Metadata(description = "Enable usage of global SSL context parameters.", label = "security")
     private boolean useGlobalSslContextParameters;
     @Metadata(description = "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context ",
               label = "security")
     private SSLContextParameters sslContextParameters;
-    @Metadata(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
-    private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
-    @Metadata(description = "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.",
-              enums = "fail,ignore,mock", label = "consumer", defaultValue = "fail")
-    private String missingOperation;
 
     public RestOpenApiComponent() {
     }
@@ -189,7 +185,7 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         return produces;
     }
 
-    public URI getSpecificationUri() {
+    public String getSpecificationUri() {
         return specificationUri;
     }
 
@@ -242,8 +238,8 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         this.produces = isMediaRange(produces, "produces");
     }
 
-    public void setSpecificationUri(final URI specificationUri) {
-        this.specificationUri = notNull(specificationUri, "specificationUri");
+    public void setSpecificationUri(String specificationUri) {
+        this.specificationUri = specificationUri;
     }
 
     public void setSslContextParameters(final SSLContextParameters sslContextParameters) {
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index df8eeafa072..90cf95b83b5 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -150,9 +150,9 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
                            + " Support for https is limited to using the JDK installed UrlHandler, and as such it can be cumbersome to setup"
                            + " TLS/SSL certificates for https (such as setting a number of javax.net.ssl JVM system properties)."
                            + " How to do that consult the JDK documentation for UrlHandler.",
-             defaultValue = RestOpenApiComponent.DEFAULT_SPECIFICATION_URI_STR,
+             defaultValue = RestOpenApiComponent.DEFAULT_SPECIFICATION_URI,
              defaultValueNote = "By default loads `openapi.json` file", label = "common")
-    private URI specificationUri;
+    private String specificationUri;
     @UriParam(description = "Enable validation of requests against the configured OpenAPI specification")
     private boolean requestValidationEnabled;
     @UriParam(description = "If request validation is enabled, this option provides the capability to customize"
@@ -181,11 +181,11 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
             operationId = after(remaining, "#");
             String spec = before(remaining, "#");
             if (spec != null && !spec.isEmpty()) {
-                specificationUri = URI.create(spec);
+                specificationUri = spec;
             }
         } else {
             if (remaining.endsWith(".json") || remaining.endsWith(".yaml") || remaining.endsWith(".yml")) {
-                specificationUri = URI.create(remaining);
+                specificationUri = remaining;
             } else {
                 operationId = remaining;
             }
@@ -376,7 +376,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         return produces;
     }
 
-    public URI getSpecificationUri() {
+    public String getSpecificationUri() {
         return specificationUri;
     }
 
@@ -413,7 +413,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         this.produces = produces;
     }
 
-    public void setSpecificationUri(final URI specificationUri) {
+    public void setSpecificationUri(String specificationUri) {
         this.specificationUri = specificationUri;
     }
 
@@ -676,7 +676,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         URI relativeURI = null;
         Set<URI> operationURIs = getURIs(operation.getServers());
         // Check if at least one of them is absolute:
-        Optional<URI> opURI = operationURIs.stream().filter(uri -> uri.isAbsolute()).findFirst();
+        Optional<URI> opURI = operationURIs.stream().filter(URI::isAbsolute).findFirst();
         if (opURI.isEmpty()) {
             // look for absolute at api level + possible relative URI for the operation
             Set<URI> apiURIs = getURIs(openApi.getServers());
@@ -713,17 +713,18 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
             return globalConfigurationHost;
         }
 
-        final String specificationScheme = specificationUri.getScheme();
-        // Perform a case insensitive "startsWith" check that works for different locales
-        String prefix = "http";
-        if (specificationUri.isAbsolute() && specificationScheme.regionMatches(true, 0, prefix, 0, prefix.length())) {
-            try {
+        try {
+            final URI uri = new URI(specificationUri);
+            final String specificationScheme = uri.getScheme();
+            // Perform a case-insensitive "startsWith" check that works for different locales
+            String prefix = "http";
+            if (uri.isAbsolute() && specificationScheme.regionMatches(true, 0, prefix, 0, prefix.length())) {
                 return new URI(
-                        specificationUri.getScheme(), specificationUri.getUserInfo(), specificationUri.getHost(),
-                        specificationUri.getPort(), null, null, null).toString();
-            } catch (final URISyntaxException e) {
-                throw new IllegalStateException("Unable to create a new URI from: " + specificationUri, e);
+                        uri.getScheme(), uri.getUserInfo(), uri.getHost(),
+                        uri.getPort(), null, null, null).toString();
             }
+        } catch (Exception e) {
+            throw new IllegalStateException("Unable to create a new URI from: " + specificationUri, e);
         }
 
         throw new IllegalStateException(
@@ -916,23 +917,22 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
      * Loads the OpenApi definition model from the given path. This delegates directly to the OpenAPI parser. If the
      * specification can't be read there is no OpenAPI object in the result.
      *
-     * @param  uri          URI of the specification
+     * @param  uri          the specification uri
      * @param  camelContext context to use
      * @return              the specification
      */
-    static OpenAPI loadSpecificationFrom(final CamelContext camelContext, final URI uri) {
-        final String uriAsString = uri.toString();
+    static OpenAPI loadSpecificationFrom(final CamelContext camelContext, final String uri) {
         final OpenAPIParser openApiParser = new OpenAPIParser();
         final ParseOptions options = new ParseOptions();
         options.setResolveFully(true);
 
         File tmpFileToDelete = null;
         try {
-            Resource resource = ResourceHelper.resolveMandatoryResource(camelContext, uriAsString);
+            Resource resource = ResourceHelper.resolveMandatoryResource(camelContext, uri);
             //if location can not be used in Swagger API (e.g. in case of "bean;")
             // the content of the resource has to be copied into a tmp file for swagger API.
             String locationToSearch;
-            if ("bean:".equals(ResourceHelper.getScheme(uriAsString))) {
+            if ("bean:".equals(ResourceHelper.getScheme(uri))) {
                 Path tmpFile = Files.createTempFile(null, null);
                 tmpFileToDelete = tmpFile.toFile();
                 tmpFileToDelete.deleteOnExit();
@@ -945,32 +945,20 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
             final SwaggerParseResult openApi = openApiParser.readLocation(locationToSearch, null, options);
 
             if (openApi != null && openApi.getOpenAPI() != null) {
-                checkV2specification(openApi.getOpenAPI(), uri);
                 return openApi.getOpenAPI();
             }
         } catch (Exception e) {
             throw new IllegalArgumentException(
-                    "The given OpenApi specification could not be loaded from `" + uri + "`.", e);
+                    "The given OpenApi specification cannot be loaded from: " + uri, e);
         } finally {
             if (tmpFileToDelete != null) {
                 FileUtil.deleteFile(tmpFileToDelete);
             }
         }
 
-        // In theory there should be a message in the parse result but it has disappeared...
+        // In theory there should be a message in the parse result, but it has disappeared...
         throw new IllegalArgumentException(
-                "The given OpenApi specification could not be loaded from `" + uri + "`.");
-    }
-
-    private static void checkV2specification(OpenAPI openAPI, final URI uri) {
-        if (openAPI.getExtensions() != null) {
-            Object swaggerVersion = openAPI.getExtensions().get("x-original-swagger-version");
-            if (swaggerVersion != null) {
-                LoggerFactory.getLogger(RestOpenApiEndpoint.class).info(
-                        "The specification {} was upgraded from {} to OpenAPI {}",
-                        uri, swaggerVersion, openAPI.getSpecVersion());
-            }
-        }
+                "The given OpenApi specification cannot be loaded from: " + uri);
     }
 
     static String pickBestScheme(final String specificationScheme, final List<String> schemes) {
diff --git a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/HttpsV3Test.java b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/HttpsV3Test.java
index 3c2078401fe..e822a25b850 100644
--- a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/HttpsV3Test.java
+++ b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/HttpsV3Test.java
@@ -18,7 +18,6 @@ package org.apache.camel.component.rest.openapi;
 
 import java.io.IOException;
 import java.net.HttpURLConnection;
-import java.net.URI;
 import java.net.URISyntaxException;
 import java.nio.file.Files;
 import java.nio.file.Paths;
@@ -123,7 +122,7 @@ public abstract class HttpsV3Test extends CamelTestSupport {
         final String host = "https://localhost:" + petstore.httpsPort();
         component.setHost(host);
         // Workaround bug resolving relative references with file URLs in swagger parser
-        component.setSpecificationUri(new URI(host + getSpecName()));
+        component.setSpecificationUri(host + getSpecName());
         //        component.setSpecificationUri(HttpsV3Test.class.getResource(getSpecName()).toURI());
         camelContext.addComponent("petStore", component);
 
diff --git a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentV3Test.java b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentV3Test.java
index cf383bdc32f..b2632cbbcaf 100644
--- a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentV3Test.java
+++ b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentV3Test.java
@@ -25,6 +25,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 
 import jakarta.xml.bind.JAXBContext;
 import jakarta.xml.bind.Marshaller;
@@ -200,14 +201,15 @@ public class RestOpenApiComponentV3Test extends CamelTestSupport {
         final RestOpenApiComponent component = new RestOpenApiComponent();
         component.setComponentName(componentName);
         component.setHost("http://localhost:" + petstore.port());
-        component.setSpecificationUri(RestOpenApiComponentV3Test.class.getResource("/openapi-v3.json").toURI());
+        component.setSpecificationUri(
+                Objects.requireNonNull(RestOpenApiComponentV3Test.class.getResource("/openapi-v3.json")).toString());
 
         camelContext.addComponent("petStore", component);
 
         final RestOpenApiComponent altPetStore = new RestOpenApiComponent();
         altPetStore.setComponentName(componentName);
         altPetStore.setHost("http://localhost:" + petstore.port());
-        altPetStore.setSpecificationUri(RestOpenApiComponentV3Test.class.getResource("/alt-openapi.json").toURI());
+        altPetStore.setSpecificationUri(RestOpenApiComponentV3Test.class.getResource("/alt-openapi.json").toString());
 
         camelContext.addComponent("altPetStore", altPetStore);
 
diff --git a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentV3YamlTest.java b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentV3YamlTest.java
index 0ae7fcd3775..38e9537907d 100644
--- a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentV3YamlTest.java
+++ b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentV3YamlTest.java
@@ -200,14 +200,14 @@ public class RestOpenApiComponentV3YamlTest extends CamelTestSupport {
         final RestOpenApiComponent component = new RestOpenApiComponent();
         component.setComponentName(componentName);
         component.setHost("http://localhost:" + petstore.port());
-        component.setSpecificationUri(RestOpenApiComponentV3YamlTest.class.getResource("/openapi-v3.yaml").toURI());
+        component.setSpecificationUri(RestOpenApiComponentV3YamlTest.class.getResource("/openapi-v3.yaml").toString());
 
         camelContext.addComponent("petStore", component);
 
         final RestOpenApiComponent altPetStore = new RestOpenApiComponent();
         altPetStore.setComponentName(componentName);
         altPetStore.setHost("http://localhost:" + petstore.port());
-        altPetStore.setSpecificationUri(RestOpenApiComponentV3YamlTest.class.getResource("/alt-openapi.yaml").toURI());
+        altPetStore.setSpecificationUri(RestOpenApiComponentV3YamlTest.class.getResource("/alt-openapi.yaml").toString());
 
         camelContext.addComponent("altPetStore", altPetStore);
 
@@ -243,7 +243,8 @@ public class RestOpenApiComponentV3YamlTest extends CamelTestSupport {
     @BeforeAll
     public static void setupStubs() throws IOException, URISyntaxException {
         petstore.stubFor(get(urlEqualTo("/openapi-v3.yaml")).willReturn(aResponse().withBody(
-                Files.readAllBytes(Paths.get(RestOpenApiComponentV3YamlTest.class.getResource("/openapi-v3.yaml").toURI())))));
+                Files.readAllBytes(
+                        Paths.get(RestOpenApiComponentV3YamlTest.class.getResource("/openapi-v3.yaml").getPath())))));
 
         petstore.stubFor(post(urlEqualTo("/api/v3/pet"))
                 .withRequestBody(equalTo(
diff --git a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiCustomValidatorCustomizerTest.java b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiCustomValidatorCustomizerTest.java
index 07a300facf4..7371d4cca36 100644
--- a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiCustomValidatorCustomizerTest.java
+++ b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiCustomValidatorCustomizerTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.component.rest.openapi;
 
-import java.net.URI;
 import java.util.Set;
 
 import javax.annotation.Nonnull;
@@ -89,7 +88,7 @@ public class RestOpenApiCustomValidatorCustomizerTest extends CamelTestSupport {
         component.setComponentName("http");
         component.setConsumes("application/json");
         component.setProduces("application/json");
-        component.setSpecificationUri(URI.create("classpath:openapi-v3.json"));
+        component.setSpecificationUri("classpath:openapi-v3.json");
         component.setRequestValidationCustomizer(new CustomRequestValidationCustomizer("Test validation error from component"));
         camelContext.addComponent("petStore", component);
 
diff --git a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointV3Test.java b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointV3Test.java
index 75276640e1f..1661583aea3 100644
--- a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointV3Test.java
+++ b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointV3Test.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.component.rest.openapi;
 
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -51,9 +50,9 @@ import static org.mockito.Mockito.when;
 
 public class RestOpenApiEndpointV3Test {
 
-    URI componentJsonUri = URI.create("component.json");
+    String componentJsonUri = "component.json";
 
-    URI endpointUri = URI.create("endpoint.json");
+    String endpointUri = "endpoint.json";
 
     @Test
     public void shouldComplainForUnknownOperations() {
@@ -381,9 +380,8 @@ public class RestOpenApiEndpointV3Test {
         final CamelContext camelContext = mock(CamelContext.class);
         when(camelContext.getClassResolver()).thenReturn(new DefaultClassResolver());
 
-        final URI uri = URI.create("non-existant.json");
         assertThrows(IllegalArgumentException.class,
-                () -> RestOpenApiEndpoint.loadSpecificationFrom(camelContext, uri));
+                () -> RestOpenApiEndpoint.loadSpecificationFrom(camelContext, "non-existant.json"));
     }
 
     @Test
diff --git a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiRequestValidationTest.java b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiRequestValidationTest.java
index cf2cf854e58..0ce95972885 100644
--- a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiRequestValidationTest.java
+++ b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiRequestValidationTest.java
@@ -22,7 +22,6 @@ import java.awt.image.BufferedImage;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.net.HttpURLConnection;
-import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.Iterator;
@@ -550,7 +549,7 @@ public class RestOpenApiRequestValidationTest extends CamelTestSupport {
     private RestOpenApiComponent createRestOpenApiComponent(String specificationUri) {
         RestOpenApiComponent component = new RestOpenApiComponent();
         component.setComponentName("http");
-        component.setSpecificationUri(URI.create("classpath:" + specificationUri));
+        component.setSpecificationUri("classpath:" + specificationUri);
         component.setConsumes("application/json");
         component.setProduces("application/json");
         component.setHost("http://localhost:" + wireMockServer.port());
diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_6.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_6.adoc
index d297df9c99e..27d2fe89a48 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_6.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_6.adoc
@@ -14,3 +14,9 @@ For example calling a route that fails due to an exception being thrown (even if
 then the variable is no longer set. Also, if the route is marked for rollback, or to stop continue routing with `.stop()`.
 
 This is the same logic that the routing engine uses, whether to continue routing the `Exchange` or not.
+
+=== camel-rest-openapi
+
+The `specifciationUri` in the `rest-api` component has changed from being a `java.net.URI` to a `String` type
+, as it uses Camels `ResourceLoader` to load from pluggable resources and also more tooling friendly.
+
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
index 064b5f66d51..a44a3419edd 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
@@ -217,8 +217,6 @@ public interface RestOpenapiComponentBuilderFactory {
          * syntax (i.e. https://api.example.com:8080). Can be overridden in
          * endpoint configuration.
          * 
-         * The option is a: &lt;code&gt;java.net.URI&lt;/code&gt; type.
-         * 
          * Default: openapi.json
          * Group: producer
          * 
@@ -226,7 +224,7 @@ public interface RestOpenapiComponentBuilderFactory {
          * @return the dsl builder
          */
         default RestOpenapiComponentBuilder specificationUri(
-                java.net.URI specificationUri) {
+                String specificationUri) {
             doSetProperty("specificationUri", specificationUri);
             return this;
         }
@@ -382,7 +380,7 @@ public interface RestOpenapiComponentBuilderFactory {
             case "basePath": ((RestOpenApiComponent) component).setBasePath((java.lang.String) value); return true;
             case "host": ((RestOpenApiComponent) component).setHost((java.lang.String) value); return true;
             case "lazyStartProducer": ((RestOpenApiComponent) component).setLazyStartProducer((boolean) value); return true;
-            case "specificationUri": ((RestOpenApiComponent) component).setSpecificationUri((java.net.URI) value); return true;
+            case "specificationUri": ((RestOpenApiComponent) component).setSpecificationUri((java.lang.String) value); return true;
             case "componentName": ((RestOpenApiComponent) component).setComponentName((java.lang.String) value); return true;
             case "consumes": ((RestOpenApiComponent) component).setConsumes((java.lang.String) value); return true;
             case "produces": ((RestOpenApiComponent) component).setProduces((java.lang.String) value); return true;


(camel) 20/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit e7991e7f33d4d9b274cf5238e965c8786db885a8
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 15:59:42 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../dsl/RestOpenapiComponentBuilderFactory.java    | 116 +++++++++++----------
 1 file changed, 59 insertions(+), 57 deletions(-)

diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
index a44a3419edd..c55ac1ad560 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
@@ -50,6 +50,21 @@ public interface RestOpenapiComponentBuilderFactory {
     interface RestOpenapiComponentBuilder
             extends
                 ComponentBuilder<RestOpenApiComponent> {
+        /**
+         * API basePath, for example /v2. Default is unset, if set overrides the
+         * value present in OpenApi specification.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: common
+         * 
+         * @param basePath the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder basePath(java.lang.String basePath) {
+            doSetProperty("basePath", basePath);
+            return this;
+        }
         /**
          * Enable validation of requests against the configured OpenAPI
          * specification.
@@ -67,6 +82,47 @@ public interface RestOpenapiComponentBuilderFactory {
             doSetProperty("requestValidationEnabled", requestValidationEnabled);
             return this;
         }
+        /**
+         * Path to the OpenApi specification file. The scheme, host base path
+         * are taken from this specification, but these can be overridden with
+         * properties on the component or endpoint level. If not given the
+         * component tries to load openapi.json resource. Note that the host
+         * defined on the component and endpoint of this Component should
+         * contain the scheme, hostname and optionally the port in the URI
+         * syntax (i.e. https://api.example.com:8080). Can be overridden in
+         * endpoint configuration.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Default: openapi.json
+         * Group: common
+         * 
+         * @param specificationUri the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder specificationUri(
+                java.lang.String specificationUri) {
+            doSetProperty("specificationUri", specificationUri);
+            return this;
+        }
+        /**
+         * If request validation is enabled, this option provides the capability
+         * to customize the creation of OpenApiInteractionValidator used to
+         * validate requests.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
+         * 
+         * Group: common (advanced)
+         * 
+         * @param requestValidationCustomizer the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder requestValidationCustomizer(
+                org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer requestValidationCustomizer) {
+            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
+            return this;
+        }
         /**
          * Allows for bridging the consumer to the Camel routing Error Handler,
          * which mean any exceptions (if possible) occurred while the Camel
@@ -147,21 +203,6 @@ public interface RestOpenapiComponentBuilderFactory {
             doSetProperty("restOpenapiProcessorStrategy", restOpenapiProcessorStrategy);
             return this;
         }
-        /**
-         * API basePath, for example /v2. Default is unset, if set overrides the
-         * value present in OpenApi specification.
-         * 
-         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
-         * 
-         * Group: producer
-         * 
-         * @param basePath the value to set
-         * @return the dsl builder
-         */
-        default RestOpenapiComponentBuilder basePath(java.lang.String basePath) {
-            doSetProperty("basePath", basePath);
-            return this;
-        }
         /**
          * Scheme hostname and port to direct the HTTP requests to in the form
          * of https://hostname:port. Can be configured at the endpoint,
@@ -207,27 +248,6 @@ public interface RestOpenapiComponentBuilderFactory {
             doSetProperty("lazyStartProducer", lazyStartProducer);
             return this;
         }
-        /**
-         * Path to the OpenApi specification file. The scheme, host base path
-         * are taken from this specification, but these can be overridden with
-         * properties on the component or endpoint level. If not given the
-         * component tries to load openapi.json resource. Note that the host
-         * defined on the component and endpoint of this Component should
-         * contain the scheme, hostname and optionally the port in the URI
-         * syntax (i.e. https://api.example.com:8080). Can be overridden in
-         * endpoint configuration.
-         * 
-         * Default: openapi.json
-         * Group: producer
-         * 
-         * @param specificationUri the value to set
-         * @return the dsl builder
-         */
-        default RestOpenapiComponentBuilder specificationUri(
-                String specificationUri) {
-            doSetProperty("specificationUri", specificationUri);
-            return this;
-        }
         /**
          * Name of the Camel component that will perform the requests. The
          * component must be present in Camel registry and it must implement
@@ -304,24 +324,6 @@ public interface RestOpenapiComponentBuilderFactory {
             doSetProperty("autowiredEnabled", autowiredEnabled);
             return this;
         }
-        /**
-         * If request validation is enabled, this option provides the capability
-         * to customize the creation of OpenApiInteractionValidator used to
-         * validate requests.
-         * 
-         * The option is a:
-         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
-         * 
-         * Group: advanced
-         * 
-         * @param requestValidationCustomizer the value to set
-         * @return the dsl builder
-         */
-        default RestOpenapiComponentBuilder requestValidationCustomizer(
-                org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer requestValidationCustomizer) {
-            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
-            return this;
-        }
         /**
          * Customize TLS parameters used by the component. If not set defaults
          * to the TLS parameters set in the Camel context.
@@ -372,20 +374,20 @@ public interface RestOpenapiComponentBuilderFactory {
                 String name,
                 Object value) {
             switch (name) {
+            case "basePath": ((RestOpenApiComponent) component).setBasePath((java.lang.String) value); return true;
             case "requestValidationEnabled": ((RestOpenApiComponent) component).setRequestValidationEnabled((boolean) value); return true;
+            case "specificationUri": ((RestOpenApiComponent) component).setSpecificationUri((java.lang.String) value); return true;
+            case "requestValidationCustomizer": ((RestOpenApiComponent) component).setRequestValidationCustomizer((org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer) value); return true;
             case "bridgeErrorHandler": ((RestOpenApiComponent) component).setBridgeErrorHandler((boolean) value); return true;
             case "missingOperation": ((RestOpenApiComponent) component).setMissingOperation((java.lang.String) value); return true;
             case "consumerComponentName": ((RestOpenApiComponent) component).setConsumerComponentName((java.lang.String) value); return true;
             case "restOpenapiProcessorStrategy": ((RestOpenApiComponent) component).setRestOpenapiProcessorStrategy((org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy) value); return true;
-            case "basePath": ((RestOpenApiComponent) component).setBasePath((java.lang.String) value); return true;
             case "host": ((RestOpenApiComponent) component).setHost((java.lang.String) value); return true;
             case "lazyStartProducer": ((RestOpenApiComponent) component).setLazyStartProducer((boolean) value); return true;
-            case "specificationUri": ((RestOpenApiComponent) component).setSpecificationUri((java.lang.String) value); return true;
             case "componentName": ((RestOpenApiComponent) component).setComponentName((java.lang.String) value); return true;
             case "consumes": ((RestOpenApiComponent) component).setConsumes((java.lang.String) value); return true;
             case "produces": ((RestOpenApiComponent) component).setProduces((java.lang.String) value); return true;
             case "autowiredEnabled": ((RestOpenApiComponent) component).setAutowiredEnabled((boolean) value); return true;
-            case "requestValidationCustomizer": ((RestOpenApiComponent) component).setRequestValidationCustomizer((org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer) value); return true;
             case "sslContextParameters": ((RestOpenApiComponent) component).setSslContextParameters((org.apache.camel.support.jsse.SSLContextParameters) value); return true;
             case "useGlobalSslContextParameters": ((RestOpenApiComponent) component).setUseGlobalSslContextParameters((boolean) value); return true;
             default: return false;


(camel) 24/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 6564e8a2751c36fd95fd10a657b91ca164215cd7
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Mar 26 09:50:40 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../java/org/apache/camel/spi/RestApiConsumerFactory.java    | 12 ++++++------
 .../org/apache/camel/spi/RestOpenApiConsumerFactory.java     | 10 +++++-----
 .../apache/camel/support/RestConsumerContextPathMatcher.java |  3 ++-
 3 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RestApiConsumerFactory.java b/core/camel-api/src/main/java/org/apache/camel/spi/RestApiConsumerFactory.java
index 82e5b9e735e..3738b260d6b 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RestApiConsumerFactory.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RestApiConsumerFactory.java
@@ -35,13 +35,13 @@ public interface RestApiConsumerFactory {
      * Creates a new REST API <a href="http://camel.apache.org/event-driven-consumer.html">Event Driven Consumer</a>,
      * which provides API listing of the REST services
      *
-     * @param  camelContext the camel context
-     * @param  processor    the processor
-     * @param  contextPath  the context-path
+     * @param  camelContext  the camel context
+     * @param  processor     the processor
+     * @param  contextPath   the context-path
      * @param  configuration REST configuration
-     * @param  parameters   additional parameters
-     * @return              a newly created REST API consumer
-     * @throws Exception    can be thrown
+     * @param  parameters    additional parameters
+     * @return               a newly created REST API consumer
+     * @throws Exception     can be thrown
      */
     Consumer createApiConsumer(
             CamelContext camelContext, Processor processor, String contextPath,
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java b/core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java
index 99a2ff513fa..79167c9d0fc 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java
@@ -16,15 +16,15 @@
  */
 package org.apache.camel.spi;
 
+import java.util.Map;
+
 import org.apache.camel.CamelContext;
 import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
 
-import java.util.Map;
-
 /**
- * Allows SPI to plugin a {@link RestOpenApiConsumerFactory} that creates the Camel {@link Consumer} responsible for handling
- * incoming HTTP requests from clients that request to access REST services which has been created using the
+ * Allows SPI to plugin a {@link RestOpenApiConsumerFactory} that creates the Camel {@link Consumer} responsible for
+ * handling incoming HTTP requests from clients that request to access REST services which has been created using the
  * <a href="http://camel.apache.org/rest-dsl">rest-dsl</a> for an entire open-api specification.
  *
  * @see RestApiConsumerFactory
@@ -39,7 +39,7 @@ public interface RestOpenApiConsumerFactory {
      *
      * @param  camelContext  the camel context
      * @param  processor     the processor
-     * @param  contextPath  the context-path
+     * @param  contextPath   the context-path
      * @param  configuration REST configuration
      * @param  parameters    additional parameters
      * @return               a newly created REST consumer
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java b/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java
index 652e13beb8b..a5d32037997 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java
@@ -122,7 +122,8 @@ public final class RestConsumerContextPathMatcher {
      * @param  consumerPaths the list of consumer context path details
      * @return               the best matched consumer, or <tt>null</tt> if none could be determined.
      */
-    public static <T> ConsumerPath<T> matchBestPath(String requestMethod, String requestPath, List<ConsumerPath<T>> consumerPaths) {
+    public static <
+            T> ConsumerPath<T> matchBestPath(String requestMethod, String requestPath, List<ConsumerPath<T>> consumerPaths) {
         ConsumerPath<T> answer = null;
 
         List<ConsumerPath<T>> candidates = new ArrayList<>();


(camel) 03/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 50d3a0bf492774b22658a7c89e75eac537b9b019
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Mar 24 12:29:31 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../camel/catalog/components/platform-http.json    |  4 +-
 .../component/platform/http/platform-http.json     |  4 +-
 .../platform/http/PlatformHttpEndpoint.java        | 10 ++---
 .../dsl/PlatformHttpEndpointBuilderFactory.java    | 32 ++++++++-------
 .../camel/kotlin/components/RestOpenapiUriDsl.kt   | 48 +++++++++++-----------
 5 files changed, 49 insertions(+), 49 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json
index 9f2fb17af36..1ad05ba7677 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json
@@ -41,8 +41,8 @@
     "matchOnUriPrefix": { "index": 9, "kind": "parameter", "displayName": "Match On Uri Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether or not the consumer should try to find a target consumer by matching the URI prefix if no exact match is found." },
     "muteException": { "index": 10, "kind": "parameter", "displayName": "Mute Exception", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "If enabled and an Exchange failed processing on the consumer side the response's body won't contain the exception's stack trace." },
     "produces": { "index": 11, "kind": "parameter", "displayName": "Produces", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type this endpoint produces, such as application\/xml or application\/json." },
-    "useCookieHandler": { "index": 12, "kind": "parameter", "displayName": "Use Cookie Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable the Cookie Handler that allows Cookie addition, expiry, and retrieval (currently only supported by camel-platform-http-vertx)" },
-    "useStreaming": { "index": 13, "kind": "parameter", "displayName": "Use Streaming", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use streaming for large requests and responses (currently only supported by camel-platform-http-vertx)" },
+    "useCookieHandler": { "index": 12, "kind": "parameter", "displayName": "Use Cookie Handler", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable the Cookie Handler that allows Cookie addition, expiry, and retrieval (currently only supported by camel-platform-http-vertx)" },
+    "useStreaming": { "index": 13, "kind": "parameter", "displayName": "Use Streaming", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use streaming for large requests and responses (currently only supported by camel-platform-http-vertx)" },
     "bridgeErrorHandler": { "index": 14, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming [...]
     "exceptionHandler": { "index": 15, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By de [...]
     "exchangePattern": { "index": 16, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
diff --git a/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json b/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json
index 9f2fb17af36..1ad05ba7677 100644
--- a/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json
+++ b/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json
@@ -41,8 +41,8 @@
     "matchOnUriPrefix": { "index": 9, "kind": "parameter", "displayName": "Match On Uri Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether or not the consumer should try to find a target consumer by matching the URI prefix if no exact match is found." },
     "muteException": { "index": 10, "kind": "parameter", "displayName": "Mute Exception", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "If enabled and an Exchange failed processing on the consumer side the response's body won't contain the exception's stack trace." },
     "produces": { "index": 11, "kind": "parameter", "displayName": "Produces", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type this endpoint produces, such as application\/xml or application\/json." },
-    "useCookieHandler": { "index": 12, "kind": "parameter", "displayName": "Use Cookie Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable the Cookie Handler that allows Cookie addition, expiry, and retrieval (currently only supported by camel-platform-http-vertx)" },
-    "useStreaming": { "index": 13, "kind": "parameter", "displayName": "Use Streaming", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use streaming for large requests and responses (currently only supported by camel-platform-http-vertx)" },
+    "useCookieHandler": { "index": 12, "kind": "parameter", "displayName": "Use Cookie Handler", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable the Cookie Handler that allows Cookie addition, expiry, and retrieval (currently only supported by camel-platform-http-vertx)" },
+    "useStreaming": { "index": 13, "kind": "parameter", "displayName": "Use Streaming", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use streaming for large requests and responses (currently only supported by camel-platform-http-vertx)" },
     "bridgeErrorHandler": { "index": 14, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming [...]
     "exceptionHandler": { "index": 15, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By de [...]
     "exchangePattern": { "index": 16, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java
index 22597ccf8ca..7cf295a1022 100644
--- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java
+++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java
@@ -73,15 +73,13 @@ public class PlatformHttpEndpoint extends DefaultEndpoint implements AsyncEndpoi
     @UriParam(label = "advanced",
               description = "To use a custom HeaderFilterStrategy to filter headers to and from Camel message.")
     private HeaderFilterStrategy headerFilterStrategy = new PlatformHttpHeaderFilterStrategy();
-    @UriParam(label = "consumer",
+    @UriParam(label = "advanced,consumer",
               description = "Whether to use streaming for large requests and responses (currently only supported by camel-platform-http-vertx)")
     private boolean useStreaming;
-
-    @UriParam(label = "consumer", description = "The properties set on a Cookies when a Cookie is added via the"
-                                                + " Cookie Handler (currently only supported by camel-platform-http-vertx)")
+    @UriParam(label = "advanced,consumer", description = "The properties set on a Cookies when a Cookie is added via the"
+                                                         + " Cookie Handler (currently only supported by camel-platform-http-vertx)")
     private CookieConfiguration cookieConfiguration = new CookieConfiguration();
-
-    @UriParam(label = "consumer",
+    @UriParam(label = "advanced,consumer",
               description = "Whether to enable the Cookie Handler that allows Cookie addition, expiry, and retrieval"
                             + " (currently only supported by camel-platform-http-vertx)")
     private boolean useCookieHandler;
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PlatformHttpEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PlatformHttpEndpointBuilderFactory.java
index 9d1d899ff44..8eb2ab379d3 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PlatformHttpEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PlatformHttpEndpointBuilderFactory.java
@@ -320,6 +320,17 @@ public interface PlatformHttpEndpointBuilderFactory {
             doSetProperty("produces", produces);
             return this;
         }
+    }
+
+    /**
+     * Advanced builder for endpoint for the Platform HTTP component.
+     */
+    public interface AdvancedPlatformHttpEndpointBuilder
+            extends
+                EndpointConsumerBuilder {
+        default PlatformHttpEndpointBuilder basic() {
+            return (PlatformHttpEndpointBuilder) this;
+        }
         /**
          * Whether to enable the Cookie Handler that allows Cookie addition,
          * expiry, and retrieval (currently only supported by
@@ -333,7 +344,7 @@ public interface PlatformHttpEndpointBuilderFactory {
          * @param useCookieHandler the value to set
          * @return the dsl builder
          */
-        default PlatformHttpEndpointBuilder useCookieHandler(
+        default AdvancedPlatformHttpEndpointBuilder useCookieHandler(
                 boolean useCookieHandler) {
             doSetProperty("useCookieHandler", useCookieHandler);
             return this;
@@ -352,7 +363,7 @@ public interface PlatformHttpEndpointBuilderFactory {
          * @param useCookieHandler the value to set
          * @return the dsl builder
          */
-        default PlatformHttpEndpointBuilder useCookieHandler(
+        default AdvancedPlatformHttpEndpointBuilder useCookieHandler(
                 String useCookieHandler) {
             doSetProperty("useCookieHandler", useCookieHandler);
             return this;
@@ -369,7 +380,8 @@ public interface PlatformHttpEndpointBuilderFactory {
          * @param useStreaming the value to set
          * @return the dsl builder
          */
-        default PlatformHttpEndpointBuilder useStreaming(boolean useStreaming) {
+        default AdvancedPlatformHttpEndpointBuilder useStreaming(
+                boolean useStreaming) {
             doSetProperty("useStreaming", useStreaming);
             return this;
         }
@@ -386,21 +398,11 @@ public interface PlatformHttpEndpointBuilderFactory {
          * @param useStreaming the value to set
          * @return the dsl builder
          */
-        default PlatformHttpEndpointBuilder useStreaming(String useStreaming) {
+        default AdvancedPlatformHttpEndpointBuilder useStreaming(
+                String useStreaming) {
             doSetProperty("useStreaming", useStreaming);
             return this;
         }
-    }
-
-    /**
-     * Advanced builder for endpoint for the Platform HTTP component.
-     */
-    public interface AdvancedPlatformHttpEndpointBuilder
-            extends
-                EndpointConsumerBuilder {
-        default PlatformHttpEndpointBuilder basic() {
-            return (PlatformHttpEndpointBuilder) this;
-        }
         /**
          * Allows for bridging the consumer to the Camel routing Error Handler,
          * which mean any exceptions (if possible) occurred while the Camel
diff --git a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
index c5670b48869..d1bc702cc63 100644
--- a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
+++ b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
@@ -77,16 +77,6 @@ public class RestOpenapiUriDsl(
     it.property("basePath", basePath)
   }
 
-  /**
-   * Name of the Camel component that will perform the requests. The component must be present in
-   * Camel registry and it must implement RestProducerFactory service provider interface. If not set
-   * CLASSPATH is searched for single component that implements RestProducerFactory SPI. Overrides
-   * component configuration.
-   */
-  public fun componentName(componentName: String) {
-    it.property("componentName", componentName)
-  }
-
   /**
    * What payload type this component capable of consuming. Could be one type, like application/json
    * or multiple types as application/json, application/xml; q=0.5 according to the RFC7231. This
@@ -117,14 +107,6 @@ public class RestOpenapiUriDsl(
     it.property("produces", produces)
   }
 
-  /**
-   * If request validation is enabled, this option provides the capability to customize the creation
-   * of OpenApiInteractionValidator used to validate requests.
-   */
-  public fun requestValidationCustomizer(requestValidationCustomizer: String) {
-    it.property("requestValidationCustomizer", requestValidationCustomizer)
-  }
-
   /**
    * Enable validation of requests against the configured OpenAPI specification
    */
@@ -140,13 +122,13 @@ public class RestOpenapiUriDsl(
   }
 
   /**
-   * Levels for specific OpenAPI request validation options. Multiple options can be specified as
-   * URI options prefixed by 'validation.'. For example,
-   * validation.request.body=ERROR&validation.request.body.unexpected=IGNORED. Supported values are
-   * INFO, ERROR, WARN & IGNORE.
+   * Name of the Camel component that will perform the requests. The component must be present in
+   * Camel registry and it must implement RestProducerFactory service provider interface. If not set
+   * CLASSPATH is searched for single component that implements RestProducerFactory SPI. Overrides
+   * component configuration.
    */
-  public fun requestValidationLevels(requestValidationLevels: String) {
-    it.property("requestValidationLevels", requestValidationLevels)
+  public fun componentName(componentName: String) {
+    it.property("componentName", componentName)
   }
 
   /**
@@ -172,4 +154,22 @@ public class RestOpenapiUriDsl(
   public fun lazyStartProducer(lazyStartProducer: Boolean) {
     it.property("lazyStartProducer", lazyStartProducer.toString())
   }
+
+  /**
+   * If request validation is enabled, this option provides the capability to customize the creation
+   * of OpenApiInteractionValidator used to validate requests.
+   */
+  public fun requestValidationCustomizer(requestValidationCustomizer: String) {
+    it.property("requestValidationCustomizer", requestValidationCustomizer)
+  }
+
+  /**
+   * Levels for specific OpenAPI request validation options. Multiple options can be specified as
+   * URI options prefixed by 'validation.'. For example,
+   * validation.request.body=ERROR&validation.request.body.unexpected=IGNORED. Supported values are
+   * INFO, ERROR, WARN & IGNORE.
+   */
+  public fun requestValidationLevels(requestValidationLevels: String) {
+    it.property("requestValidationLevels", requestValidationLevels)
+  }
 }


(camel) 09/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 8a5b391679c673f39714ee4e19c44885d54685a9
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 06:40:17 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../camel/catalog/components/rest-openapi.json     |  54 ++-
 .../builder/endpoint/StaticEndpointBuilders.java   |  10 +-
 .../dsl/RestOpenApiEndpointBuilderFactory.java     | 534 ++++++++++++++++++---
 .../camel/kotlin/components/RestOpenapiUriDsl.kt   |  86 +++-
 4 files changed, 587 insertions(+), 97 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index 9242b3b9735..0c3036935d0 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -18,35 +18,41 @@
     "async": false,
     "api": false,
     "consumerOnly": false,
-    "producerOnly": true,
+    "producerOnly": false,
     "lenientProperties": false,
     "remote": true
   },
   "componentProperties": {
-    "basePath": { "index": 0, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
-    "host": { "index": 1, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "requestValidationEnabled": { "index": 3, "kind": "property", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "specificationUri": { "index": 4, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
-    "componentName": { "index": 5, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
-    "consumes": { "index": 6, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
-    "produces": { "index": 7, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi sp [...]
-    "autowiredEnabled": { "index": 8, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
-    "requestValidationCustomizer": { "index": 9, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator us [...]
-    "sslContextParameters": { "index": 10, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
-    "useGlobalSslContextParameters": { "index": 11, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
+    "requestValidationEnabled": { "index": 0, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
+    "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
+    "consumerComponentName": { "index": 2, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
+    "basePath": { "index": 3, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
+    "host": { "index": 4, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 5, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "specificationUri": { "index": 6, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
+    "componentName": { "index": 7, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
+    "consumes": { "index": 8, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
+    "produces": { "index": 9, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi sp [...]
+    "autowiredEnabled": { "index": 10, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
+    "requestValidationCustomizer": { "index": 11, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
+    "sslContextParameters": { "index": 12, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
+    "useGlobalSslContextParameters": { "index": 13, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
-    "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
-    "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification." },
-    "basePath": { "index": 2, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "consumes": { "index": 3, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
-    "host": { "index": 4, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
-    "produces": { "index": 5, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overri [...]
-    "requestValidationEnabled": { "index": 6, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "componentName": { "index": 7, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
-    "lazyStartProducer": { "index": 8, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...]
-    "requestValidationCustomizer": { "index": 9, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
-    "requestValidationLevels": { "index": 10, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
+    "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not give [...]
+    "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
+    "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
+    "bridgeErrorHandler": { "index": 3, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
+    "consumerComponentName": { "index": 4, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
+    "exceptionHandler": { "index": 5, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
+    "exchangePattern": { "index": 6, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
+    "basePath": { "index": 7, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
+    "consumes": { "index": 8, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
+    "host": { "index": 9, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
+    "produces": { "index": 10, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
+    "componentName": { "index": 11, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
+    "lazyStartProducer": { "index": 12, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "requestValidationCustomizer": { "index": 13, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
+    "requestValidationLevels": { "index": 14, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
index fadc4fc1fdf..40b01f7e5e7 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
@@ -12751,8 +12751,9 @@ public class StaticEndpointBuilders {
      * loads openapi.json file
      * Default value: openapi.json
      * 
-     * Path parameter: operationId (required)
-     * ID of the operation from the OpenApi specification.
+     * Path parameter: operationId
+     * ID of the operation from the OpenApi specification. This is required when
+     * using producer
      * 
      * @param path specificationUri#operationId
      * @return the dsl builder
@@ -12788,8 +12789,9 @@ public class StaticEndpointBuilders {
      * loads openapi.json file
      * Default value: openapi.json
      * 
-     * Path parameter: operationId (required)
-     * ID of the operation from the OpenApi specification.
+     * Path parameter: operationId
+     * ID of the operation from the OpenApi specification. This is required when
+     * using producer
      * 
      * @param componentName to use a custom component name for the endpoint
      * instead of the default name
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
index 47d90bae33f..a0454445e2a 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
@@ -36,13 +36,331 @@ public interface RestOpenApiEndpointBuilderFactory {
 
 
     /**
-     * Builder for endpoint for the REST OpenApi component.
+     * Builder for endpoint consumers for the REST OpenApi component.
      */
-    public interface RestOpenApiEndpointBuilder
+    public interface RestOpenApiEndpointConsumerBuilder
+            extends
+                EndpointConsumerBuilder {
+        default AdvancedRestOpenApiEndpointConsumerBuilder advanced() {
+            return (AdvancedRestOpenApiEndpointConsumerBuilder) this;
+        }
+        /**
+         * Enable validation of requests against the configured OpenAPI
+         * specification.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param requestValidationEnabled the value to set
+         * @return the dsl builder
+         */
+        default RestOpenApiEndpointConsumerBuilder requestValidationEnabled(
+                boolean requestValidationEnabled) {
+            doSetProperty("requestValidationEnabled", requestValidationEnabled);
+            return this;
+        }
+        /**
+         * Enable validation of requests against the configured OpenAPI
+         * specification.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param requestValidationEnabled the value to set
+         * @return the dsl builder
+         */
+        default RestOpenApiEndpointConsumerBuilder requestValidationEnabled(
+                String requestValidationEnabled) {
+            doSetProperty("requestValidationEnabled", requestValidationEnabled);
+            return this;
+        }
+    }
+
+    /**
+     * Advanced builder for endpoint consumers for the REST OpenApi component.
+     */
+    public interface AdvancedRestOpenApiEndpointConsumerBuilder
+            extends
+                EndpointConsumerBuilder {
+        default RestOpenApiEndpointConsumerBuilder basic() {
+            return (RestOpenApiEndpointConsumerBuilder) this;
+        }
+        /**
+         * Allows for bridging the consumer to the Camel routing Error Handler,
+         * which mean any exceptions (if possible) occurred while the Camel
+         * consumer is trying to pickup incoming messages, or the likes, will
+         * now be processed as a message and handled by the routing Error
+         * Handler. Important: This is only possible if the 3rd party component
+         * allows Camel to be alerted if an exception was thrown. Some
+         * components handle this internally only, and therefore
+         * bridgeErrorHandler is not possible. In other situations we may
+         * improve the Camel component to hook into the 3rd party component and
+         * make this possible for future releases. By default the consumer will
+         * use the org.apache.camel.spi.ExceptionHandler to deal with
+         * exceptions, that will be logged at WARN or ERROR level and ignored.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: consumer (advanced)
+         * 
+         * @param bridgeErrorHandler the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder bridgeErrorHandler(
+                boolean bridgeErrorHandler) {
+            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+            return this;
+        }
+        /**
+         * Allows for bridging the consumer to the Camel routing Error Handler,
+         * which mean any exceptions (if possible) occurred while the Camel
+         * consumer is trying to pickup incoming messages, or the likes, will
+         * now be processed as a message and handled by the routing Error
+         * Handler. Important: This is only possible if the 3rd party component
+         * allows Camel to be alerted if an exception was thrown. Some
+         * components handle this internally only, and therefore
+         * bridgeErrorHandler is not possible. In other situations we may
+         * improve the Camel component to hook into the 3rd party component and
+         * make this possible for future releases. By default the consumer will
+         * use the org.apache.camel.spi.ExceptionHandler to deal with
+         * exceptions, that will be logged at WARN or ERROR level and ignored.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: consumer (advanced)
+         * 
+         * @param bridgeErrorHandler the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder bridgeErrorHandler(
+                String bridgeErrorHandler) {
+            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+            return this;
+        }
+        /**
+         * Name of the Camel component that will service the requests. The
+         * component must be present in Camel registry and it must implement
+         * RestOpenApiConsumerFactory service provider interface. If not set
+         * CLASSPATH is searched for single component that implements
+         * RestOpenApiConsumerFactory SPI. Overrides component configuration.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param consumerComponentName the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder consumerComponentName(
+                String consumerComponentName) {
+            doSetProperty("consumerComponentName", consumerComponentName);
+            return this;
+        }
+        /**
+         * To let the consumer use a custom ExceptionHandler. Notice if the
+         * option bridgeErrorHandler is enabled then this option is not in use.
+         * By default the consumer will deal with exceptions, that will be
+         * logged at WARN or ERROR level and ignored.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.spi.ExceptionHandler&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param exceptionHandler the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder exceptionHandler(
+                org.apache.camel.spi.ExceptionHandler exceptionHandler) {
+            doSetProperty("exceptionHandler", exceptionHandler);
+            return this;
+        }
+        /**
+         * To let the consumer use a custom ExceptionHandler. Notice if the
+         * option bridgeErrorHandler is enabled then this option is not in use.
+         * By default the consumer will deal with exceptions, that will be
+         * logged at WARN or ERROR level and ignored.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.spi.ExceptionHandler&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param exceptionHandler the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder exceptionHandler(
+                String exceptionHandler) {
+            doSetProperty("exceptionHandler", exceptionHandler);
+            return this;
+        }
+        /**
+         * Sets the exchange pattern when the consumer creates an exchange.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.ExchangePattern&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param exchangePattern the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder exchangePattern(
+                org.apache.camel.ExchangePattern exchangePattern) {
+            doSetProperty("exchangePattern", exchangePattern);
+            return this;
+        }
+        /**
+         * Sets the exchange pattern when the consumer creates an exchange.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.ExchangePattern&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param exchangePattern the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder exchangePattern(
+                String exchangePattern) {
+            doSetProperty("exchangePattern", exchangePattern);
+            return this;
+        }
+        /**
+         * If request validation is enabled, this option provides the capability
+         * to customize the creation of OpenApiInteractionValidator used to
+         * validate requests.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param requestValidationCustomizer the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder requestValidationCustomizer(
+                org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer requestValidationCustomizer) {
+            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
+            return this;
+        }
+        /**
+         * If request validation is enabled, this option provides the capability
+         * to customize the creation of OpenApiInteractionValidator used to
+         * validate requests.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param requestValidationCustomizer the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder requestValidationCustomizer(
+                String requestValidationCustomizer) {
+            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
+            return this;
+        }
+        /**
+         * Levels for specific OpenAPI request validation options. Multiple
+         * options can be specified as URI options prefixed by 'validation.'.
+         * For example,
+         * validation.request.body=ERROR&amp;amp;validation.request.body.unexpected=IGNORED. Supported values are INFO, ERROR, WARN &amp;amp; IGNORE.
+         * 
+         * The option is a: &lt;code&gt;java.util.Map&amp;lt;java.lang.String,
+         * java.lang.Object&amp;gt;&lt;/code&gt; type.
+         * The option is multivalued, and you can use the
+         * requestValidationLevels(String, Object) method to add a value (call
+         * the method multiple times to set more values).
+         * 
+         * Group: advanced
+         * 
+         * @param key the option key
+         * @param value the option value
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder requestValidationLevels(
+                String key,
+                Object value) {
+            doSetMultiValueProperty("requestValidationLevels", "validation." + key, value);
+            return this;
+        }
+        /**
+         * Levels for specific OpenAPI request validation options. Multiple
+         * options can be specified as URI options prefixed by 'validation.'.
+         * For example,
+         * validation.request.body=ERROR&amp;amp;validation.request.body.unexpected=IGNORED. Supported values are INFO, ERROR, WARN &amp;amp; IGNORE.
+         * 
+         * The option is a: &lt;code&gt;java.util.Map&amp;lt;java.lang.String,
+         * java.lang.Object&amp;gt;&lt;/code&gt; type.
+         * The option is multivalued, and you can use the
+         * requestValidationLevels(String, Object) method to add a value (call
+         * the method multiple times to set more values).
+         * 
+         * Group: advanced
+         * 
+         * @param values the values
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder requestValidationLevels(
+                Map values) {
+            doSetMultiValueProperties("requestValidationLevels", "validation.", values);
+            return this;
+        }
+    }
+
+    /**
+     * Builder for endpoint producers for the REST OpenApi component.
+     */
+    public interface RestOpenApiEndpointProducerBuilder
             extends
                 EndpointProducerBuilder {
-        default AdvancedRestOpenApiEndpointBuilder advanced() {
-            return (AdvancedRestOpenApiEndpointBuilder) this;
+        default AdvancedRestOpenApiEndpointProducerBuilder advanced() {
+            return (AdvancedRestOpenApiEndpointProducerBuilder) this;
+        }
+        /**
+         * Enable validation of requests against the configured OpenAPI
+         * specification.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param requestValidationEnabled the value to set
+         * @return the dsl builder
+         */
+        default RestOpenApiEndpointProducerBuilder requestValidationEnabled(
+                boolean requestValidationEnabled) {
+            doSetProperty("requestValidationEnabled", requestValidationEnabled);
+            return this;
+        }
+        /**
+         * Enable validation of requests against the configured OpenAPI
+         * specification.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param requestValidationEnabled the value to set
+         * @return the dsl builder
+         */
+        default RestOpenApiEndpointProducerBuilder requestValidationEnabled(
+                String requestValidationEnabled) {
+            doSetProperty("requestValidationEnabled", requestValidationEnabled);
+            return this;
         }
         /**
          * API basePath, for example /v3. Default is unset, if set overrides the
@@ -56,7 +374,7 @@ public interface RestOpenApiEndpointBuilderFactory {
          * @param basePath the value to set
          * @return the dsl builder
          */
-        default RestOpenApiEndpointBuilder basePath(String basePath) {
+        default RestOpenApiEndpointProducerBuilder basePath(String basePath) {
             doSetProperty("basePath", basePath);
             return this;
         }
@@ -74,7 +392,7 @@ public interface RestOpenApiEndpointBuilderFactory {
          * @param consumes the value to set
          * @return the dsl builder
          */
-        default RestOpenApiEndpointBuilder consumes(String consumes) {
+        default RestOpenApiEndpointProducerBuilder consumes(String consumes) {
             doSetProperty("consumes", consumes);
             return this;
         }
@@ -94,7 +412,7 @@ public interface RestOpenApiEndpointBuilderFactory {
          * @param host the value to set
          * @return the dsl builder
          */
-        default RestOpenApiEndpointBuilder host(String host) {
+        default RestOpenApiEndpointProducerBuilder host(String host) {
             doSetProperty("host", host);
             return this;
         }
@@ -111,55 +429,20 @@ public interface RestOpenApiEndpointBuilderFactory {
          * @param produces the value to set
          * @return the dsl builder
          */
-        default RestOpenApiEndpointBuilder produces(String produces) {
+        default RestOpenApiEndpointProducerBuilder produces(String produces) {
             doSetProperty("produces", produces);
             return this;
         }
-        /**
-         * Enable validation of requests against the configured OpenAPI
-         * specification.
-         * 
-         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
-         * 
-         * Default: false
-         * Group: producer
-         * 
-         * @param requestValidationEnabled the value to set
-         * @return the dsl builder
-         */
-        default RestOpenApiEndpointBuilder requestValidationEnabled(
-                boolean requestValidationEnabled) {
-            doSetProperty("requestValidationEnabled", requestValidationEnabled);
-            return this;
-        }
-        /**
-         * Enable validation of requests against the configured OpenAPI
-         * specification.
-         * 
-         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
-         * type.
-         * 
-         * Default: false
-         * Group: producer
-         * 
-         * @param requestValidationEnabled the value to set
-         * @return the dsl builder
-         */
-        default RestOpenApiEndpointBuilder requestValidationEnabled(
-                String requestValidationEnabled) {
-            doSetProperty("requestValidationEnabled", requestValidationEnabled);
-            return this;
-        }
     }
 
     /**
-     * Advanced builder for endpoint for the REST OpenApi component.
+     * Advanced builder for endpoint producers for the REST OpenApi component.
      */
-    public interface AdvancedRestOpenApiEndpointBuilder
+    public interface AdvancedRestOpenApiEndpointProducerBuilder
             extends
                 EndpointProducerBuilder {
-        default RestOpenApiEndpointBuilder basic() {
-            return (RestOpenApiEndpointBuilder) this;
+        default RestOpenApiEndpointProducerBuilder basic() {
+            return (RestOpenApiEndpointProducerBuilder) this;
         }
         /**
          * Name of the Camel component that will perform the requests. The
@@ -175,7 +458,7 @@ public interface RestOpenApiEndpointBuilderFactory {
          * @param componentName the value to set
          * @return the dsl builder
          */
-        default AdvancedRestOpenApiEndpointBuilder componentName(
+        default AdvancedRestOpenApiEndpointProducerBuilder componentName(
                 String componentName) {
             doSetProperty("componentName", componentName);
             return this;
@@ -199,7 +482,7 @@ public interface RestOpenApiEndpointBuilderFactory {
          * @param lazyStartProducer the value to set
          * @return the dsl builder
          */
-        default AdvancedRestOpenApiEndpointBuilder lazyStartProducer(
+        default AdvancedRestOpenApiEndpointProducerBuilder lazyStartProducer(
                 boolean lazyStartProducer) {
             doSetProperty("lazyStartProducer", lazyStartProducer);
             return this;
@@ -224,11 +507,152 @@ public interface RestOpenApiEndpointBuilderFactory {
          * @param lazyStartProducer the value to set
          * @return the dsl builder
          */
-        default AdvancedRestOpenApiEndpointBuilder lazyStartProducer(
+        default AdvancedRestOpenApiEndpointProducerBuilder lazyStartProducer(
                 String lazyStartProducer) {
             doSetProperty("lazyStartProducer", lazyStartProducer);
             return this;
         }
+        /**
+         * If request validation is enabled, this option provides the capability
+         * to customize the creation of OpenApiInteractionValidator used to
+         * validate requests.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param requestValidationCustomizer the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointProducerBuilder requestValidationCustomizer(
+                org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer requestValidationCustomizer) {
+            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
+            return this;
+        }
+        /**
+         * If request validation is enabled, this option provides the capability
+         * to customize the creation of OpenApiInteractionValidator used to
+         * validate requests.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param requestValidationCustomizer the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointProducerBuilder requestValidationCustomizer(
+                String requestValidationCustomizer) {
+            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
+            return this;
+        }
+        /**
+         * Levels for specific OpenAPI request validation options. Multiple
+         * options can be specified as URI options prefixed by 'validation.'.
+         * For example,
+         * validation.request.body=ERROR&amp;amp;validation.request.body.unexpected=IGNORED. Supported values are INFO, ERROR, WARN &amp;amp; IGNORE.
+         * 
+         * The option is a: &lt;code&gt;java.util.Map&amp;lt;java.lang.String,
+         * java.lang.Object&amp;gt;&lt;/code&gt; type.
+         * The option is multivalued, and you can use the
+         * requestValidationLevels(String, Object) method to add a value (call
+         * the method multiple times to set more values).
+         * 
+         * Group: advanced
+         * 
+         * @param key the option key
+         * @param value the option value
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointProducerBuilder requestValidationLevels(
+                String key,
+                Object value) {
+            doSetMultiValueProperty("requestValidationLevels", "validation." + key, value);
+            return this;
+        }
+        /**
+         * Levels for specific OpenAPI request validation options. Multiple
+         * options can be specified as URI options prefixed by 'validation.'.
+         * For example,
+         * validation.request.body=ERROR&amp;amp;validation.request.body.unexpected=IGNORED. Supported values are INFO, ERROR, WARN &amp;amp; IGNORE.
+         * 
+         * The option is a: &lt;code&gt;java.util.Map&amp;lt;java.lang.String,
+         * java.lang.Object&amp;gt;&lt;/code&gt; type.
+         * The option is multivalued, and you can use the
+         * requestValidationLevels(String, Object) method to add a value (call
+         * the method multiple times to set more values).
+         * 
+         * Group: advanced
+         * 
+         * @param values the values
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointProducerBuilder requestValidationLevels(
+                Map values) {
+            doSetMultiValueProperties("requestValidationLevels", "validation.", values);
+            return this;
+        }
+    }
+
+    /**
+     * Builder for endpoint for the REST OpenApi component.
+     */
+    public interface RestOpenApiEndpointBuilder
+            extends
+                RestOpenApiEndpointConsumerBuilder,
+                RestOpenApiEndpointProducerBuilder {
+        default AdvancedRestOpenApiEndpointBuilder advanced() {
+            return (AdvancedRestOpenApiEndpointBuilder) this;
+        }
+        /**
+         * Enable validation of requests against the configured OpenAPI
+         * specification.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param requestValidationEnabled the value to set
+         * @return the dsl builder
+         */
+        default RestOpenApiEndpointBuilder requestValidationEnabled(
+                boolean requestValidationEnabled) {
+            doSetProperty("requestValidationEnabled", requestValidationEnabled);
+            return this;
+        }
+        /**
+         * Enable validation of requests against the configured OpenAPI
+         * specification.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: common
+         * 
+         * @param requestValidationEnabled the value to set
+         * @return the dsl builder
+         */
+        default RestOpenApiEndpointBuilder requestValidationEnabled(
+                String requestValidationEnabled) {
+            doSetProperty("requestValidationEnabled", requestValidationEnabled);
+            return this;
+        }
+    }
+
+    /**
+     * Advanced builder for endpoint for the REST OpenApi component.
+     */
+    public interface AdvancedRestOpenApiEndpointBuilder
+            extends
+                AdvancedRestOpenApiEndpointConsumerBuilder,
+                AdvancedRestOpenApiEndpointProducerBuilder {
+        default RestOpenApiEndpointBuilder basic() {
+            return (RestOpenApiEndpointBuilder) this;
+        }
         /**
          * If request validation is enabled, this option provides the capability
          * to customize the creation of OpenApiInteractionValidator used to
@@ -341,8 +765,9 @@ public interface RestOpenApiEndpointBuilderFactory {
          * UrlHandler. Default value notice: By default loads openapi.json file
          * Default value: openapi.json
          * 
-         * Path parameter: operationId (required)
-         * ID of the operation from the OpenApi specification.
+         * Path parameter: operationId
+         * ID of the operation from the OpenApi specification. This is required
+         * when using producer
          * 
          * @param path specificationUri#operationId
          * @return the dsl builder
@@ -377,8 +802,9 @@ public interface RestOpenApiEndpointBuilderFactory {
          * UrlHandler. Default value notice: By default loads openapi.json file
          * Default value: openapi.json
          * 
-         * Path parameter: operationId (required)
-         * ID of the operation from the OpenApi specification.
+         * Path parameter: operationId
+         * ID of the operation from the OpenApi specification. This is required
+         * when using producer
          * 
          * @param componentName to use a custom component name for the endpoint
          * instead of the default name
diff --git a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
index d1bc702cc63..6f22f587c84 100644
--- a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
+++ b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
@@ -62,13 +62,83 @@ public class RestOpenapiUriDsl(
   }
 
   /**
-   * ID of the operation from the OpenApi specification.
+   * ID of the operation from the OpenApi specification. This is required when using producer
    */
   public fun operationId(operationId: String) {
     this.operationId = operationId
     it.url("$specificationUri#$operationId")
   }
 
+  /**
+   * Enable validation of requests against the configured OpenAPI specification
+   */
+  public fun requestValidationEnabled(requestValidationEnabled: String) {
+    it.property("requestValidationEnabled", requestValidationEnabled)
+  }
+
+  /**
+   * Enable validation of requests against the configured OpenAPI specification
+   */
+  public fun requestValidationEnabled(requestValidationEnabled: Boolean) {
+    it.property("requestValidationEnabled", requestValidationEnabled.toString())
+  }
+
+  /**
+   * Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions
+   * (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the
+   * likes, will now be processed as a message and handled by the routing Error Handler. Important:
+   * This is only possible if the 3rd party component allows Camel to be alerted if an exception was
+   * thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not
+   * possible. In other situations we may improve the Camel component to hook into the 3rd party
+   * component and make this possible for future releases. By default the consumer will use the
+   * org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or
+   * ERROR level and ignored.
+   */
+  public fun bridgeErrorHandler(bridgeErrorHandler: String) {
+    it.property("bridgeErrorHandler", bridgeErrorHandler)
+  }
+
+  /**
+   * Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions
+   * (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the
+   * likes, will now be processed as a message and handled by the routing Error Handler. Important:
+   * This is only possible if the 3rd party component allows Camel to be alerted if an exception was
+   * thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not
+   * possible. In other situations we may improve the Camel component to hook into the 3rd party
+   * component and make this possible for future releases. By default the consumer will use the
+   * org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or
+   * ERROR level and ignored.
+   */
+  public fun bridgeErrorHandler(bridgeErrorHandler: Boolean) {
+    it.property("bridgeErrorHandler", bridgeErrorHandler.toString())
+  }
+
+  /**
+   * Name of the Camel component that will service the requests. The component must be present in
+   * Camel registry and it must implement RestOpenApiConsumerFactory service provider interface. If not
+   * set CLASSPATH is searched for single component that implements RestOpenApiConsumerFactory SPI.
+   * Overrides component configuration.
+   */
+  public fun consumerComponentName(consumerComponentName: String) {
+    it.property("consumerComponentName", consumerComponentName)
+  }
+
+  /**
+   * To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is
+   * enabled then this option is not in use. By default the consumer will deal with exceptions, that
+   * will be logged at WARN or ERROR level and ignored.
+   */
+  public fun exceptionHandler(exceptionHandler: String) {
+    it.property("exceptionHandler", exceptionHandler)
+  }
+
+  /**
+   * Sets the exchange pattern when the consumer creates an exchange.
+   */
+  public fun exchangePattern(exchangePattern: String) {
+    it.property("exchangePattern", exchangePattern)
+  }
+
   /**
    * API basePath, for example /v3. Default is unset, if set overrides the value present in OpenApi
    * specification and in the component configuration.
@@ -107,20 +177,6 @@ public class RestOpenapiUriDsl(
     it.property("produces", produces)
   }
 
-  /**
-   * Enable validation of requests against the configured OpenAPI specification
-   */
-  public fun requestValidationEnabled(requestValidationEnabled: String) {
-    it.property("requestValidationEnabled", requestValidationEnabled)
-  }
-
-  /**
-   * Enable validation of requests against the configured OpenAPI specification
-   */
-  public fun requestValidationEnabled(requestValidationEnabled: Boolean) {
-    it.property("requestValidationEnabled", requestValidationEnabled.toString())
-  }
-
   /**
    * Name of the Camel component that will perform the requests. The component must be present in
    * Camel registry and it must implement RestProducerFactory service provider interface. If not set


(camel) 37/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit cf2d5d01329a31dc2f015112a7f4cd82f050ef7c
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 18:14:35 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../camel/catalog/components/rest-openapi.json     | 27 +++++++++++-----------
 .../org/apache/camel/catalog/models/openApi.json   |  5 ++--
 .../apache/camel/catalog/schemas/camel-spring.xsd  | 18 ++++++++++++---
 .../dsl/yaml/deserializers/ModelDeserializers.java |  6 +++++
 .../generated/resources/schema/camelYamlDsl.json   |  5 ++++
 5 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index e224a0d248e..7c83b6b9cb4 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -27,19 +27,20 @@
     "requestValidationEnabled": { "index": 1, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "specificationUri": { "index": 2, "kind": "property", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
     "requestValidationCustomizer": { "index": 3, "kind": "property", "displayName": "Request Validation Customizer", "group": "common (advanced)", "label": "common,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInterac [...]
-    "bridgeErrorHandler": { "index": 4, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
-    "missingOperation": { "index": 5, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
-    "consumerComponentName": { "index": 6, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "mockIncludePattern": { "index": 7, "kind": "property", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sepa [...]
-    "restOpenapiProcessorStrategy": { "index": 8, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "host": { "index": 9, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 10, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fai [...]
-    "componentName": { "index": 11, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
-    "consumes": { "index": 12, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
-    "produces": { "index": 13, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
-    "autowiredEnabled": { "index": 14, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
-    "sslContextParameters": { "index": 15, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
-    "useGlobalSslContextParameters": { "index": 16, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
+    "apiContextPath": { "index": 4, "kind": "property", "displayName": "Api Context Path", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the context-path to use for servicing the OpenAPI specification" },
+    "bridgeErrorHandler": { "index": 5, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
+    "missingOperation": { "index": 6, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
+    "consumerComponentName": { "index": 7, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
+    "mockIncludePattern": { "index": 8, "kind": "property", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sepa [...]
+    "restOpenapiProcessorStrategy": { "index": 9, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "host": { "index": 10, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
+    "lazyStartProducer": { "index": 11, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fai [...]
+    "componentName": { "index": 12, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
+    "consumes": { "index": 13, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
+    "produces": { "index": 14, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
+    "autowiredEnabled": { "index": 15, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
+    "sslContextParameters": { "index": 16, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
+    "useGlobalSslContextParameters": { "index": 17, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json
index f1292c7c300..2d064458544 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json
@@ -17,7 +17,8 @@
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST service has been disabled then it cannot be enabled later at runtime." },
     "specification": { "index": 3, "kind": "attribute", "displayName": "Specification", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Path to the OpenApi specification file." },
     "routeId": { "index": 4, "kind": "attribute", "displayName": "Route Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of the route" },
-    "missingOperation": { "index": 5, "kind": "attribute", "displayName": "Missing Operation", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
-    "mockIncludePattern": { "index": 6, "kind": "attribute", "displayName": "Mock Include Pattern", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma." }
+    "requestValidationEnabled": { "index": 5, "kind": "attribute", "displayName": "Request Validation Enabled", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable validation of the client request to check that the request contains valid and expected data." },
+    "missingOperation": { "index": 6, "kind": "attribute", "displayName": "Missing Operation", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
+    "mockIncludePattern": { "index": 7, "kind": "attribute", "displayName": "Mock Include Pattern", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma." }
   }
 }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index d800a098830..745fd32593f 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -16387,7 +16387,9 @@ The flow used by the OAuth2 security scheme. Valid values are implicit, password
   <xs:complexType name="openApiDefinition">
     <xs:complexContent>
       <xs:extension base="tns:optionalIdentifiedDefinition">
-        <xs:sequence/>
+        <xs:sequence>
+          <xs:element minOccurs="0" name="apiContextPath" type="xs:string"/>
+        </xs:sequence>
         <xs:attribute name="specification" type="xs:string" use="required">
           <xs:annotation>
             <xs:documentation xml:lang="en">
@@ -16412,6 +16414,16 @@ Sets the id of the route.
 <![CDATA[
 Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST
 service has been disabled then it cannot be enabled later at runtime. Default value: false
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="requestValidationEnabled" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Whether to enable validation of the client request to check that the request contains valid and expected data. Default
+value: false
 ]]>
             </xs:documentation>
           </xs:annotation>
@@ -16757,8 +16769,8 @@ or camel-netty-http that includes a HTTP server.
       <xs:annotation>
         <xs:documentation xml:lang="en">
 <![CDATA[
-Sets a leading API context-path the REST API services will be using. This can be used when using components such as
-camel-servlet where the deployed web application is deployed using a context-path.
+Sets a leading context-path the REST API will be using. This can be used when using components such as camel-servlet
+where the deployed web application is deployed using a context-path.
 ]]>
         </xs:documentation>
       </xs:annotation>
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index 53d3374a1d2..a987d4bdd4b 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -10362,6 +10362,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "id", type = "string", description = "Sets the id of this node", displayName = "Id"),
                     @YamlProperty(name = "missingOperation", type = "enum:fail,ignore,mock", defaultValue = "fail", description = "Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.", displayName = "Missing Operation"),
                     @YamlProperty(name = "mockIncludePattern", type = "string", defaultValue = "classpath:camel-mock/**", description = "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma.", displayName = "Mock Include Pattern"),
+                    @YamlProperty(name = "requestValidationEnabled", type = "boolean", description = "Whether to enable validation of the client request to check that the request contains valid and expected data.", displayName = "Request Validation Enabled"),
                     @YamlProperty(name = "routeId", type = "string", description = "Sets the id of the route", displayName = "Route Id"),
                     @YamlProperty(name = "specification", type = "string", required = true, description = "Path to the OpenApi specification file.", displayName = "Specification")
             }
@@ -10396,6 +10397,11 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setMockIncludePattern(val);
                     break;
                 }
+                case "requestValidationEnabled": {
+                    String val = asText(node);
+                    target.setRequestValidationEnabled(val);
+                    break;
+                }
                 case "routeId": {
                     String val = asText(node);
                     target.setRouteId(val);
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index e03199e5b61..c790de79194 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -14702,6 +14702,11 @@
             "description" : "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma.",
             "default" : "classpath:camel-mock/**"
           },
+          "requestValidationEnabled" : {
+            "type" : "boolean",
+            "title" : "Request Validation Enabled",
+            "description" : "Whether to enable validation of the client request to check that the request contains valid and expected data."
+          },
           "routeId" : {
             "type" : "string",
             "title" : "Route Id",


(camel) 10/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 4467903c031064f3a5437a2930c81011033a0009
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 08:17:18 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../vertx/PlatformHttpRestOpenApiConsumerTest.java |  2 +-
 ...va => DefaultRestOpenapiProcessorStrategy.java} | 55 +++++--------
 .../rest/openapi/RestOpenApiConsumerPath.java      | 53 ++++++++++++
 .../rest/openapi/RestOpenApiProcessor.java         | 93 ++++++++++++++++------
 .../rest/openapi/RestOpenapiProcessorStrategy.java | 27 +++++++
 .../support/RestConsumerContextPathMatcher.java    |  3 +-
 6 files changed, 170 insertions(+), 63 deletions(-)

diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
index 7fb2ec61db9..ab01d018caa 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
@@ -45,7 +45,7 @@ public class PlatformHttpRestOpenApiConsumerTest {
 
             given()
                     .when()
-                    .get("/api/v3/getPetById")
+                    .get("/api/v3/pet/123")
                     .then()
                     .statusCode(200)
                     .body(equalTo("{\"pet\": \"tony the tiger\"}"));
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
similarity index 62%
copy from components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
copy to components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index bc9767eaadd..965b9625519 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -16,30 +16,36 @@
  */
 package org.apache.camel.component.rest.openapi;
 
-import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.Operation;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.AsyncProducer;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
+import org.apache.camel.NonManagedService;
 import org.apache.camel.spi.ProducerCache;
 import org.apache.camel.support.cache.DefaultProducerCache;
-import org.apache.camel.support.processor.DelegateAsyncProcessor;
 import org.apache.camel.support.service.ServiceHelper;
+import org.apache.camel.support.service.ServiceSupport;
 
-public class RestOpenApiProcessor extends DelegateAsyncProcessor implements CamelContextAware {
+public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
+        implements RestOpenapiProcessorStrategy, CamelContextAware, NonManagedService {
 
     private CamelContext camelContext;
-    private final OpenAPI openAPI;
-    private final String basePath;
     private ProducerCache producerCache;
 
-    public RestOpenApiProcessor(OpenAPI openAPI, String basePath, Processor processor) {
-        super(processor);
-        this.basePath = basePath;
-        this.openAPI = openAPI;
+    @Override
+    public boolean process(Operation operation, String path, Exchange exchange, AsyncCallback callback) {
+        Endpoint e = camelContext.getEndpoint("direct:" + operation.getOperationId());
+        AsyncProducer p = producerCache.acquireProducer(e);
+        return p.process(exchange, doneSync -> {
+            try {
+                producerCache.releaseProducer(e, p);
+            } finally {
+                callback.done(doneSync);
+            }
+        });
     }
 
     @Override
@@ -52,46 +58,21 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
         this.camelContext = camelContext;
     }
 
-    @Override
-    public boolean process(Exchange exchange, AsyncCallback callback) {
-        String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);
-        if (path != null && path.startsWith(basePath)) {
-            path = path.substring(basePath.length() + 1);
-        }
-
-        // TODO: choose processor strategy (mapping by operation id -> direct)
-        // TODO: check if valid operation according to OpenApi
-        // TODO: validate GET/POST etc
-        // TODO: 404 and so on
-        // TODO: binding
-
-        Endpoint e = camelContext.getEndpoint("direct:" + path);
-        AsyncProducer p = producerCache.acquireProducer(e);
-        return p.process(exchange, new AsyncCallback() {
-            @Override
-            public void done(boolean doneSync) {
-                producerCache.releaseProducer(e, p);
-                callback.done(doneSync);
-            }
-        });
-    }
-
     @Override
     protected void doInit() throws Exception {
-        super.doInit();
+        // TODO: non-managed
         producerCache = new DefaultProducerCache(this, getCamelContext(), 1000);
         ServiceHelper.initService(producerCache);
     }
 
     @Override
     protected void doStart() throws Exception {
-        super.doStart();
         ServiceHelper.startService(producerCache);
     }
 
     @Override
     protected void doStop() throws Exception {
-        super.doStop();
         ServiceHelper.stopService(producerCache);
     }
+
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiConsumerPath.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiConsumerPath.java
new file mode 100644
index 00000000000..d94684eb9b2
--- /dev/null
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiConsumerPath.java
@@ -0,0 +1,53 @@
+/*
+ * 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.apache.camel.component.rest.openapi;
+
+import io.swagger.v3.oas.models.Operation;
+import org.apache.camel.support.RestConsumerContextPathMatcher;
+
+class RestOpenApiConsumerPath implements RestConsumerContextPathMatcher.ConsumerPath<Operation> {
+
+    private final String verb;
+    private final String path;
+    private final Operation consumer;
+
+    public RestOpenApiConsumerPath(String verb, String path, Operation consumer) {
+        this.verb = verb;
+        this.path = path;
+        this.consumer = consumer;
+    }
+
+    @Override
+    public String getRestrictMethod() {
+        return verb;
+    }
+
+    @Override
+    public String getConsumerPath() {
+        return path;
+    }
+
+    @Override
+    public Operation getConsumer() {
+        return consumer;
+    }
+
+    @Override
+    public boolean isMatchOnUriPrefix() {
+        return false;
+    }
+}
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index bc9767eaadd..283327a3c6a 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -16,16 +16,19 @@
  */
 package org.apache.camel.component.rest.openapi;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
+
 import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.PathItem;
 import org.apache.camel.AsyncCallback;
-import org.apache.camel.AsyncProducer;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
-import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
-import org.apache.camel.spi.ProducerCache;
-import org.apache.camel.support.cache.DefaultProducerCache;
+import org.apache.camel.support.RestConsumerContextPathMatcher;
 import org.apache.camel.support.processor.DelegateAsyncProcessor;
 import org.apache.camel.support.service.ServiceHelper;
 
@@ -34,12 +37,14 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
     private CamelContext camelContext;
     private final OpenAPI openAPI;
     private final String basePath;
-    private ProducerCache producerCache;
+    private final List<RestConsumerContextPathMatcher.ConsumerPath<Operation>> paths = new ArrayList<>();
+    private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy;
 
     public RestOpenApiProcessor(OpenAPI openAPI, String basePath, Processor processor) {
         super(processor);
         this.basePath = basePath;
         this.openAPI = openAPI;
+        this.restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
     }
 
     @Override
@@ -52,46 +57,88 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
         this.camelContext = camelContext;
     }
 
+    public RestOpenapiProcessorStrategy getRestOpenapiProcessorStrategy() {
+        return restOpenapiProcessorStrategy;
+    }
+
+    public void setRestOpenapiProcessorStrategy(RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) {
+        this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy;
+    }
+
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
-        String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);
-        if (path != null && path.startsWith(basePath)) {
-            path = path.substring(basePath.length() + 1);
-        }
-
-        // TODO: choose processor strategy (mapping by operation id -> direct)
         // TODO: check if valid operation according to OpenApi
         // TODO: validate GET/POST etc
+        // TODO: RequestValidator
         // TODO: 404 and so on
         // TODO: binding
 
-        Endpoint e = camelContext.getEndpoint("direct:" + path);
-        AsyncProducer p = producerCache.acquireProducer(e);
-        return p.process(exchange, new AsyncCallback() {
-            @Override
-            public void done(boolean doneSync) {
-                producerCache.releaseProducer(e, p);
-                callback.done(doneSync);
+        String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);
+        if (path != null && path.startsWith(basePath)) {
+            path = path.substring(basePath.length());
+        }
+        String verb = exchange.getMessage().getHeader(Exchange.HTTP_METHOD, String.class);
+
+        RestConsumerContextPathMatcher.ConsumerPath<Operation> m
+                = RestConsumerContextPathMatcher.matchBestPath(verb, path, paths);
+        if (m != null) {
+            Operation o = m.getConsumer();
+            return restOpenapiProcessorStrategy.process(o, path, exchange, callback);
+        }
+
+        // no operation found so it's a 404
+        exchange.setException(new RejectedExecutionException());
+        exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 404);
+        callback.done(true);
+        return true;
+    }
+
+    protected Operation asOperation(PathItem item, String verb) {
+        return switch (verb) {
+            case "GET" -> item.getGet();
+            case "DELETE" -> item.getDelete();
+            case "HEAD" -> item.getHead();
+            case "PATCH" -> item.getPatch();
+            case "OPTIONS" -> item.getOptions();
+            case "PUT" -> item.getPut();
+            case "POST" -> item.getPost();
+            default -> null;
+        };
+    }
+
+    @Override
+    protected void doBuild() throws Exception {
+        super.doBuild();
+
+        // register all openapi paths
+        for (var e : openAPI.getPaths().entrySet()) {
+            String path = e.getKey(); // path
+            for (var o : e.getValue().readOperationsMap().entrySet()) {
+                String v = o.getKey().name(); // verb
+                paths.add(new RestOpenApiConsumerPath(v, path, o.getValue()));
             }
-        });
+        }
+
+        CamelContextAware.trySetCamelContext(restOpenapiProcessorStrategy, getCamelContext());
+        ServiceHelper.buildService(restOpenapiProcessorStrategy);
     }
 
     @Override
     protected void doInit() throws Exception {
         super.doInit();
-        producerCache = new DefaultProducerCache(this, getCamelContext(), 1000);
-        ServiceHelper.initService(producerCache);
+        ServiceHelper.initService(restOpenapiProcessorStrategy);
     }
 
     @Override
     protected void doStart() throws Exception {
         super.doStart();
-        ServiceHelper.startService(producerCache);
+        ServiceHelper.startService(restOpenapiProcessorStrategy);
     }
 
     @Override
     protected void doStop() throws Exception {
         super.doStop();
-        ServiceHelper.stopService(producerCache);
+        paths.clear();
+        ServiceHelper.stopService(restOpenapiProcessorStrategy);
     }
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
new file mode 100644
index 00000000000..baaeac1d81e
--- /dev/null
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
@@ -0,0 +1,27 @@
+/*
+ * 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.apache.camel.component.rest.openapi;
+
+import io.swagger.v3.oas.models.Operation;
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+
+public interface RestOpenapiProcessorStrategy {
+
+    boolean process(Operation operation, String path, Exchange exchange, AsyncCallback callback);
+
+}
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java b/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java
index a5d32037997..652e13beb8b 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java
@@ -122,8 +122,7 @@ public final class RestConsumerContextPathMatcher {
      * @param  consumerPaths the list of consumer context path details
      * @return               the best matched consumer, or <tt>null</tt> if none could be determined.
      */
-    public static <
-            T> ConsumerPath<T> matchBestPath(String requestMethod, String requestPath, List<ConsumerPath<T>> consumerPaths) {
+    public static <T> ConsumerPath<T> matchBestPath(String requestMethod, String requestPath, List<ConsumerPath<T>> consumerPaths) {
         ConsumerPath<T> answer = null;
 
         List<ConsumerPath<T>> candidates = new ArrayList<>();


(camel) 17/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit a41b4587d37a601611efc0019500dd1777c815b8
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 12:48:57 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../camel/catalog/components/rest-openapi.json     | 54 +++++++++---------
 .../vertx/PlatformHttpRestOpenApiConsumerTest.java | 65 +++++++++++++++++++++-
 .../openapi/RestOpenApiComponentConfigurer.java    |  6 ++
 .../openapi/RestOpenApiEndpointConfigurer.java     |  6 ++
 .../openapi/RestOpenApiEndpointUriFactory.java     |  3 +-
 .../camel/component/rest/openapi/rest-openapi.json | 54 +++++++++---------
 .../DefaultRestOpenapiProcessorStrategy.java       | 63 +++++++++++++++++++++
 .../rest/openapi/RestOpenApiComponent.java         | 12 ++++
 .../rest/openapi/RestOpenApiEndpoint.java          | 11 ++++
 .../rest/openapi/RestOpenApiProcessor.java         |  8 ++-
 .../rest/openapi/RestOpenapiProcessorStrategy.java | 23 ++++++++
 .../dsl/RestOpenApiEndpointBuilderFactory.java     | 17 ++++++
 .../camel/kotlin/components/RestOpenapiUriDsl.kt   |  8 +++
 13 files changed, 272 insertions(+), 58 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index 22998ee020e..fae90af3743 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -25,36 +25,38 @@
   "componentProperties": {
     "requestValidationEnabled": { "index": 0, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
-    "consumerComponentName": { "index": 2, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "restOpenapiProcessorStrategy": { "index": 3, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "basePath": { "index": 4, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
-    "host": { "index": 5, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 6, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "specificationUri": { "index": 7, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
-    "componentName": { "index": 8, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
-    "consumes": { "index": 9, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
-    "produces": { "index": 10, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
-    "autowiredEnabled": { "index": 11, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
-    "requestValidationCustomizer": { "index": 12, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
-    "sslContextParameters": { "index": 13, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
-    "useGlobalSslContextParameters": { "index": 14, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
+    "missingOperation": { "index": 2, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "dummy" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route." },
+    "consumerComponentName": { "index": 3, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
+    "restOpenapiProcessorStrategy": { "index": 4, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 5, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
+    "host": { "index": 6, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 7, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "specificationUri": { "index": 8, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
+    "componentName": { "index": 9, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
+    "consumes": { "index": 10, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
+    "produces": { "index": 11, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
+    "autowiredEnabled": { "index": 12, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
+    "requestValidationCustomizer": { "index": 13, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
+    "sslContextParameters": { "index": 14, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
+    "useGlobalSslContextParameters": { "index": 15, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not give [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
     "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "bridgeErrorHandler": { "index": 3, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
-    "consumerComponentName": { "index": 4, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
-    "exceptionHandler": { "index": 5, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
-    "exchangePattern": { "index": 6, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
-    "restOpenapiProcessorStrategy": { "index": 7, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "basePath": { "index": 8, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "consumes": { "index": 9, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
-    "host": { "index": 10, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
-    "produces": { "index": 11, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
-    "componentName": { "index": 12, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
-    "lazyStartProducer": { "index": 13, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
-    "requestValidationCustomizer": { "index": 14, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
-    "requestValidationLevels": { "index": 15, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
+    "missingOperation": { "index": 3, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "dummy" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route." },
+    "bridgeErrorHandler": { "index": 4, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
+    "consumerComponentName": { "index": 5, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
+    "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
+    "exchangePattern": { "index": 7, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
+    "restOpenapiProcessorStrategy": { "index": 8, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 9, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
+    "consumes": { "index": 10, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
+    "host": { "index": 11, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
+    "produces": { "index": 12, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
+    "componentName": { "index": 13, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
+    "lazyStartProducer": { "index": 14, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "requestValidationCustomizer": { "index": 15, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
+    "requestValidationLevels": { "index": 16, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
index 1ea0a976913..c41839ef21f 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
@@ -18,10 +18,12 @@ package org.apache.camel.component.platform.http.vertx;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import static io.restassured.RestAssured.given;
 import static org.hamcrest.Matchers.equalTo;
+import static org.junit.jupiter.api.Assertions.fail;
 
 public class PlatformHttpRestOpenApiConsumerTest {
 
@@ -29,6 +31,37 @@ public class PlatformHttpRestOpenApiConsumerTest {
     public void testRestOpenApi() throws Exception {
         final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
 
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("rest-openapi:classpath:openapi-v3.json?missingOperation=ignore")
+                            .log("dummy");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .get("/api/v3/pet/123")
+                    .then()
+                    .statusCode(200)
+                    .body(equalTo("{\"pet\": \"tony the tiger\"}"));
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testRestOpenApiDevMode() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+        // run in developer mode
+        context.getCamelContextExtension().setProfile("dev");
+
         try {
             context.addRoutes(new RouteBuilder() {
                 @Override
@@ -54,6 +87,32 @@ public class PlatformHttpRestOpenApiConsumerTest {
         }
     }
 
+    @Test
+    public void testRestOpenApiMissingOperation() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("rest-openapi:classpath:openapi-v3.json?missingOperation=fail")
+                            .log("dummy");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+            fail();
+        } catch (IllegalArgumentException e) {
+            Assertions.assertTrue(
+                    e.getMessage().startsWith("OpenAPI specification has 18 unmapped operations to corresponding routes"));
+        } finally {
+            context.stop();
+        }
+    }
+
     @Test
     public void testRestOpenApiNotFound() throws Exception {
         final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
@@ -62,7 +121,7 @@ public class PlatformHttpRestOpenApiConsumerTest {
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() {
-                    from("rest-openapi:classpath:openapi-v3.json")
+                    from("rest-openapi:classpath:openapi-v3.json?missingOperation=ignore")
                             .log("dummy");
 
                     from("direct:getPetById")
@@ -90,7 +149,7 @@ public class PlatformHttpRestOpenApiConsumerTest {
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() {
-                    from("rest-openapi:classpath:openapi-v3.json")
+                    from("rest-openapi:classpath:openapi-v3.json?missingOperation=ignore")
                             .log("dummy");
 
                     from("direct:getPetById")
@@ -118,7 +177,7 @@ public class PlatformHttpRestOpenApiConsumerTest {
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() {
-                    from("rest-openapi:classpath:openapi-v3.json?requestValidationEnabled=true")
+                    from("rest-openapi:classpath:openapi-v3.json?missingOperation=ignore&requestValidationEnabled=true")
                             .log("dummy");
 
                     from("direct:updatePet")
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
index 89b6cc3ccc6..96dd8f657ec 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
@@ -35,6 +35,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "host": target.setHost(property(camelContext, java.lang.String.class, value)); return true;
         case "lazystartproducer":
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+        case "missingoperation":
+        case "missingOperation": target.setMissingOperation(property(camelContext, java.lang.String.class, value)); return true;
         case "produces": target.setProduces(property(camelContext, java.lang.String.class, value)); return true;
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": target.setRequestValidationCustomizer(property(camelContext, org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer.class, value)); return true;
@@ -69,6 +71,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "host": return java.lang.String.class;
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
+        case "missingoperation":
+        case "missingOperation": return java.lang.String.class;
         case "produces": return java.lang.String.class;
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": return org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer.class;
@@ -104,6 +108,8 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "host": return target.getHost();
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
+        case "missingoperation":
+        case "missingOperation": return target.getMissingOperation();
         case "produces": return target.getProduces();
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": return target.getRequestValidationCustomizer();
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
index 7877105d046..6766a773f15 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
@@ -37,6 +37,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         case "host": target.setHost(property(camelContext, java.lang.String.class, value)); return true;
         case "lazystartproducer":
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+        case "missingoperation":
+        case "missingOperation": target.setMissingOperation(property(camelContext, java.lang.String.class, value)); return true;
         case "produces": target.setProduces(property(camelContext, java.lang.String.class, value)); return true;
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": target.setRequestValidationCustomizer(property(camelContext, org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer.class, value)); return true;
@@ -69,6 +71,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         case "host": return java.lang.String.class;
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
+        case "missingoperation":
+        case "missingOperation": return java.lang.String.class;
         case "produces": return java.lang.String.class;
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": return org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer.class;
@@ -102,6 +106,8 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         case "host": return target.getHost();
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
+        case "missingoperation":
+        case "missingOperation": return target.getMissingOperation();
         case "produces": return target.getProduces();
         case "requestvalidationcustomizer":
         case "requestValidationCustomizer": return target.getRequestValidationCustomizer();
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
index 1117c2366cf..f841c7ad9af 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
@@ -21,7 +21,7 @@ public class RestOpenApiEndpointUriFactory extends org.apache.camel.support.comp
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(16);
+        Set<String> props = new HashSet<>(17);
         props.add("basePath");
         props.add("bridgeErrorHandler");
         props.add("componentName");
@@ -31,6 +31,7 @@ public class RestOpenApiEndpointUriFactory extends org.apache.camel.support.comp
         props.add("exchangePattern");
         props.add("host");
         props.add("lazyStartProducer");
+        props.add("missingOperation");
         props.add("operationId");
         props.add("produces");
         props.add("requestValidationCustomizer");
diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index 22998ee020e..fae90af3743 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -25,36 +25,38 @@
   "componentProperties": {
     "requestValidationEnabled": { "index": 0, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
-    "consumerComponentName": { "index": 2, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "restOpenapiProcessorStrategy": { "index": 3, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "basePath": { "index": 4, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
-    "host": { "index": 5, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 6, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "specificationUri": { "index": 7, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
-    "componentName": { "index": 8, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
-    "consumes": { "index": 9, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
-    "produces": { "index": 10, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
-    "autowiredEnabled": { "index": 11, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
-    "requestValidationCustomizer": { "index": 12, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
-    "sslContextParameters": { "index": 13, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
-    "useGlobalSslContextParameters": { "index": 14, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
+    "missingOperation": { "index": 2, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "dummy" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route." },
+    "consumerComponentName": { "index": 3, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
+    "restOpenapiProcessorStrategy": { "index": 4, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 5, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
+    "host": { "index": 6, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 7, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "specificationUri": { "index": 8, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
+    "componentName": { "index": 9, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
+    "consumes": { "index": 10, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
+    "produces": { "index": 11, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
+    "autowiredEnabled": { "index": 12, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
+    "requestValidationCustomizer": { "index": 13, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
+    "sslContextParameters": { "index": 14, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
+    "useGlobalSslContextParameters": { "index": 15, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not give [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
     "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "bridgeErrorHandler": { "index": 3, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
-    "consumerComponentName": { "index": 4, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
-    "exceptionHandler": { "index": 5, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
-    "exchangePattern": { "index": 6, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
-    "restOpenapiProcessorStrategy": { "index": 7, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "basePath": { "index": 8, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "consumes": { "index": 9, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
-    "host": { "index": 10, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
-    "produces": { "index": 11, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
-    "componentName": { "index": 12, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
-    "lazyStartProducer": { "index": 13, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
-    "requestValidationCustomizer": { "index": 14, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
-    "requestValidationLevels": { "index": 15, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
+    "missingOperation": { "index": 3, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "dummy" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route." },
+    "bridgeErrorHandler": { "index": 4, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
+    "consumerComponentName": { "index": 5, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
+    "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
+    "exchangePattern": { "index": 7, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
+    "restOpenapiProcessorStrategy": { "index": 8, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 9, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
+    "consumes": { "index": 10, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
+    "host": { "index": 11, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
+    "produces": { "index": 12, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
+    "componentName": { "index": 13, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
+    "lazyStartProducer": { "index": 14, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "requestValidationCustomizer": { "index": 15, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
+    "requestValidationLevels": { "index": 16, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index b46795d5a46..f150912331e 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -16,6 +16,11 @@
  */
 package org.apache.camel.component.rest.openapi;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.AsyncProducer;
@@ -24,10 +29,13 @@ import org.apache.camel.CamelContextAware;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
 import org.apache.camel.NonManagedService;
+import org.apache.camel.Route;
 import org.apache.camel.spi.ProducerCache;
 import org.apache.camel.support.cache.DefaultProducerCache;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.support.service.ServiceSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Default {@link RestOpenapiProcessorStrategy} that links the Rest DSL to routes called via direct:operationId.
@@ -35,9 +43,50 @@ import org.apache.camel.support.service.ServiceSupport;
 public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         implements RestOpenapiProcessorStrategy, CamelContextAware, NonManagedService {
 
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultRestOpenapiProcessorStrategy.class);
+
     private CamelContext camelContext;
     private ProducerCache producerCache;
     private String component = "direct";
+    private String missingOperation;
+
+    @Override
+    public void validateOpenApi(OpenAPI openAPI) throws Exception {
+        List<String> ids = new ArrayList<>();
+        for (var e : openAPI.getPaths().entrySet()) {
+            for (var o : e.getValue().readOperations()) {
+                String id = o.getOperationId();
+                ids.add(component + "://" + id);
+            }
+        }
+        // should have routes with all
+        List<String> existing = new ArrayList<>();
+        for (Route route : camelContext.getRoutes()) {
+            String base = route.getEndpoint().getEndpointBaseUri();
+            existing.add(base);
+        }
+
+        // all ids must have a route
+        ids.removeAll(existing);
+        if (!ids.isEmpty()) {
+            String missing = ids.stream()
+                    .sorted()
+                    .map(id -> id.replace("://", ":"))
+                    .collect(Collectors.joining("\n\t"));
+            String msg = String.format(
+                    "OpenAPI specification has %d unmapped operations to corresponding routes: %n\t%s",
+                    ids.size(),
+                    missing);
+
+            if ("fail".equalsIgnoreCase(missingOperation)) {
+                throw new IllegalArgumentException(msg);
+            } else if ("ignore".equalsIgnoreCase(missingOperation)) {
+                LOG.warn(msg + ". This validation error is ignored.");
+            } else if ("dev".equalsIgnoreCase(missingOperation)) {
+                LOG.warn(msg + ". This validation error is ignored when running in developer mode (profile=dev).");
+            }
+        }
+    }
 
     @Override
     public boolean process(Operation operation, String path, Exchange exchange, AsyncCallback callback) {
@@ -73,10 +122,24 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         this.component = component;
     }
 
+    public String getMissingOperation() {
+        return missingOperation;
+    }
+
+    public void setMissingOperation(String missingOperation) {
+        this.missingOperation = missingOperation;
+    }
+
     @Override
     protected void doInit() throws Exception {
         producerCache = new DefaultProducerCache(this, getCamelContext(), 1000);
         ServiceHelper.initService(producerCache);
+
+        // automatic adjust missing operation to fail, and ignore if you use developer mode
+        if (missingOperation == null) {
+            boolean dev = "dev".equalsIgnoreCase(camelContext.getCamelContextExtension().getProfile());
+            missingOperation = dev ? "dev" : "fail";
+        }
     }
 
     @Override
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index 98ea9e91fe4..e248acbc4aa 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -141,6 +141,9 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
     private SSLContextParameters sslContextParameters;
     @Metadata(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
     private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
+    @Metadata(description = "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route.",
+              enums = "fail,ignore,dummy", label = "consumer", defaultValue = "fail")
+    private String missingOperation;
 
     public RestOpenApiComponent() {
     }
@@ -157,6 +160,7 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         endpoint.setRequestValidationEnabled(isRequestValidationEnabled());
         endpoint.setRequestValidationLevels(PropertiesHelper.extractProperties(parameters, "validation."));
         endpoint.setRestOpenapiProcessorStrategy(getRestOpenapiProcessorStrategy());
+        endpoint.setMissingOperation(getMissingOperation());
         setProperties(endpoint, parameters);
         return endpoint;
     }
@@ -206,6 +210,14 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy;
     }
 
+    public String getMissingOperation() {
+        return missingOperation;
+    }
+
+    public void setMissingOperation(String missingOperation) {
+        this.missingOperation = missingOperation;
+    }
+
     public void setBasePath(final String basePath) {
         this.basePath = notEmpty(basePath, "basePath");
     }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 2c55358dacf..9dbcd3df054 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -166,6 +166,9 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     private Map<String, Object> requestValidationLevels = new HashMap<>();
     @UriParam(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
     private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy;
+    @UriParam(description = "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route.",
+              enums = "fail,ignore,dummy", label = "consumer", defaultValue = "fail")
+    private String missingOperation;
 
     public RestOpenApiEndpoint() {
         // help tooling instantiate endpoint
@@ -447,6 +450,14 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy;
     }
 
+    public String getMissingOperation() {
+        return missingOperation;
+    }
+
+    public void setMissingOperation(String missingOperation) {
+        this.missingOperation = missingOperation;
+    }
+
     Producer createProducerFor(
             final OpenAPI openapi, final Operation operation, final String method,
             final String uriTemplate)
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index 39184eecadf..d7a6c0e50fa 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -141,6 +141,7 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
     protected void doBuild() throws Exception {
         super.doBuild();
 
+        CamelContextAware.trySetCamelContext(restOpenapiProcessorStrategy, getCamelContext());
         // register all openapi paths
         for (var e : openAPI.getPaths().entrySet()) {
             String path = e.getKey(); // path
@@ -149,15 +150,18 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
                 paths.add(new RestOpenApiConsumerPath(v, path, o.getValue()));
             }
         }
-
-        CamelContextAware.trySetCamelContext(restOpenapiProcessorStrategy, getCamelContext());
         ServiceHelper.buildService(restOpenapiProcessorStrategy);
     }
 
     @Override
     protected void doInit() throws Exception {
         super.doInit();
+
+        restOpenapiProcessorStrategy.setMissingOperation(endpoint.getMissingOperation());
         ServiceHelper.initService(restOpenapiProcessorStrategy);
+
+        // validate openapi contract
+        restOpenapiProcessorStrategy.validateOpenApi(openAPI);
     }
 
     @Override
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
index 80fb0501865..dcb1938dae2 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.component.rest.openapi;
 
+import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.Exchange;
@@ -25,6 +26,28 @@ import org.apache.camel.Exchange;
  */
 public interface RestOpenapiProcessorStrategy {
 
+    /**
+     * Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to
+     * a corresponding route.
+     */
+    void setMissingOperation(String missingOperation);
+
+    /**
+     * Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to
+     * a corresponding route.
+     */
+    String getMissingOperation();
+
+    /**
+     * Validates the OpenAPI specification on startup
+     *
+     * @param  openAPI   the openapi specification
+     * @throws Exception is thrown if validation error on startup
+     */
+    default void validateOpenApi(OpenAPI openAPI) throws Exception {
+        // noop
+    }
+
     /**
      * Strategy for processing the Rest DSL operation
      *
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
index 10936800f56..d3545200a49 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
@@ -79,6 +79,23 @@ public interface RestOpenApiEndpointBuilderFactory {
             doSetProperty("requestValidationEnabled", requestValidationEnabled);
             return this;
         }
+        /**
+         * Whether the consumer should fail,ignore or return a dummy response
+         * for OpenAPI operations that are not mapped to a corresponding route.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Default: fail
+         * Group: consumer
+         * 
+         * @param missingOperation the value to set
+         * @return the dsl builder
+         */
+        default RestOpenApiEndpointConsumerBuilder missingOperation(
+                String missingOperation) {
+            doSetProperty("missingOperation", missingOperation);
+            return this;
+        }
     }
 
     /**
diff --git a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
index 9827040e0b9..915720a83d6 100644
--- a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
+++ b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
@@ -83,6 +83,14 @@ public class RestOpenapiUriDsl(
     it.property("requestValidationEnabled", requestValidationEnabled.toString())
   }
 
+  /**
+   * Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that
+   * are not mapped to a corresponding route.
+   */
+  public fun missingOperation(missingOperation: String) {
+    it.property("missingOperation", missingOperation)
+  }
+
   /**
    * Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions
    * (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the


(camel) 34/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit e5b688c502a41564ed8a2308d902aab456b3baf8
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 14:45:06 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 ...PlatformHttpRestOpenApiConsumerRestDslTest.java |  3 +-
 .../rest/openapi/RestOpenApiEndpoint.java          |  4 +-
 .../org/apache/camel/model/rest/openApi.json       |  5 +-
 .../apache/camel/model/rest/OpenApiDefinition.java | 67 +++++++++++++++++-----
 .../apache/camel/model/rest/RestDefinition.java    | 20 +++----
 .../java/org/apache/camel/xml/in/ModelParser.java  |  1 +
 .../java/org/apache/camel/xml/out/ModelWriter.java |  1 +
 .../org/apache/camel/yaml/out/ModelWriter.java     |  1 +
 8 files changed, 69 insertions(+), 33 deletions(-)

diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
index b836248ab33..c659090e47a 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
@@ -213,8 +213,7 @@ public class PlatformHttpRestOpenApiConsumerRestDslTest {
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() {
-                    rest().clientRequestValidation(true)
-                            .openApi().specification("openapi-v3.json").missingOperation("ignore");
+                    rest().openApi().specification("openapi-v3.json").missingOperation("ignore").requestValidationEnabled();
 
                     from("direct:updatePet")
                             .setBody().constant("{\"pet\": \"tony the tiger\"}");
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 0a29a7c18b5..da2620cb248 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -36,7 +36,6 @@ import java.util.stream.Stream;
 import com.atlassian.oai.validator.OpenApiInteractionValidator;
 import com.atlassian.oai.validator.report.LevelResolver;
 import com.atlassian.oai.validator.report.ValidationReport;
-import io.swagger.parser.OpenAPIParser;
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
 import io.swagger.v3.oas.models.PathItem;
@@ -48,6 +47,7 @@ import io.swagger.v3.oas.models.security.SecurityRequirement;
 import io.swagger.v3.oas.models.security.SecurityScheme;
 import io.swagger.v3.oas.models.security.SecurityScheme.In;
 import io.swagger.v3.oas.models.servers.Server;
+import io.swagger.v3.parser.OpenAPIV3Parser;
 import io.swagger.v3.parser.core.models.ParseOptions;
 import io.swagger.v3.parser.core.models.SwaggerParseResult;
 import org.apache.camel.CamelContext;
@@ -902,7 +902,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
      * @return              the specification
      */
     static OpenAPI loadSpecificationFrom(final CamelContext camelContext, final String uri) {
-        final OpenAPIParser openApiParser = new OpenAPIParser();
+        final OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
         final ParseOptions options = new ParseOptions();
         options.setResolveFully(true);
 
diff --git a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json
index f1292c7c300..2d064458544 100644
--- a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json
+++ b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json
@@ -17,7 +17,8 @@
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST service has been disabled then it cannot be enabled later at runtime." },
     "specification": { "index": 3, "kind": "attribute", "displayName": "Specification", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Path to the OpenApi specification file." },
     "routeId": { "index": 4, "kind": "attribute", "displayName": "Route Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of the route" },
-    "missingOperation": { "index": 5, "kind": "attribute", "displayName": "Missing Operation", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
-    "mockIncludePattern": { "index": 6, "kind": "attribute", "displayName": "Mock Include Pattern", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma." }
+    "requestValidationEnabled": { "index": 5, "kind": "attribute", "displayName": "Request Validation Enabled", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable validation of the client request to check that the request contains valid and expected data." },
+    "missingOperation": { "index": 6, "kind": "attribute", "displayName": "Missing Operation", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
+    "mockIncludePattern": { "index": 7, "kind": "attribute", "displayName": "Mock Include Pattern", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma." }
   }
 }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
index 91183e54fee..6579c6837e1 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
@@ -46,6 +46,9 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
     @Metadata(label = "advanced", javaType = "java.lang.Boolean")
     private String disabled;
     @XmlAttribute
+    @Metadata(javaType = "java.lang.Boolean")
+    private String requestValidationEnabled;
+    @XmlAttribute
     @Metadata(enums = "fail,ignore,mock", defaultValue = "fail")
     private String missingOperation;
     @XmlAttribute
@@ -94,12 +97,24 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
         this.disabled = disabled;
     }
 
+    public String getRequestValidationEnabled() {
+        return requestValidationEnabled;
+    }
+
+    /**
+     * Whether to enable validation of the client request to check that the request contains valid and expected data.
+     */
+    public void setRequestValidationEnabled(String requestValidationEnabled) {
+        this.requestValidationEnabled = requestValidationEnabled;
+    }
+
     public String getMissingOperation() {
         return missingOperation;
     }
 
     /**
-     * Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.
+     * Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding
+     * route.
      */
     public void setMissingOperation(String missingOperation) {
         this.missingOperation = missingOperation;
@@ -110,8 +125,8 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
     }
 
     /**
-     * Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern.
-     * Multiple patterns can be specified separated by comma.
+     * Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple
+     * patterns can be specified separated by comma.
      */
     public void setMockIncludePattern(String mockIncludePattern) {
         this.mockIncludePattern = mockIncludePattern;
@@ -140,8 +155,8 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
     }
 
     /**
-     * Whether to enable api-doc that exposes the OpenAPI specification file as a REST endpoint.
-     * This allows clients to obtain the specification from the running Camel application.
+     * Whether to enable api-doc that exposes the OpenAPI specification file as a REST endpoint. This allows clients to
+     * obtain the specification from the running Camel application.
      */
     public OpenApiDefinition apiContextPath(String apiDoc) {
         this.apiContextPath = apiDoc;
@@ -149,8 +164,31 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
     }
 
     /**
-     * Whether to disable the OpenAPI entirely. Once the OpenAPI has been disabled then it cannot be
-     * enabled later at runtime.
+     * Whether to enable validation of the client request to check that the request contains valid and expected data.
+     */
+    public OpenApiDefinition requestValidationEnabled(String requestValidationEnabled) {
+        this.requestValidationEnabled = requestValidationEnabled;
+        return this;
+    }
+
+    /**
+     * Whether to enable validation of the client request to check that the request contains valid and expected data.
+     */
+    public OpenApiDefinition requestValidationEnabled(boolean requestValidationEnabled) {
+        this.requestValidationEnabled = requestValidationEnabled ? "true" : "false";
+        return this;
+    }
+
+    /**
+     * Whether to enable validation of the client request to check that the request contains valid and expected data.
+     */
+    public OpenApiDefinition requestValidationEnabled() {
+        return requestValidationEnabled(true);
+    }
+
+    /**
+     * Whether to disable the OpenAPI entirely. Once the OpenAPI has been disabled then it cannot be enabled later at
+     * runtime.
      */
     public OpenApiDefinition disabled(String disabled) {
         this.disabled = disabled;
@@ -158,8 +196,8 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
     }
 
     /**
-     * Whether to disable the OpenAPI entirely. Once the OpenAPI has been disabled then it cannot be
-     * enabled later at runtime.
+     * Whether to disable the OpenAPI entirely. Once the OpenAPI has been disabled then it cannot be enabled later at
+     * runtime.
      */
     public OpenApiDefinition disabled(boolean disabled) {
         this.disabled = disabled ? "true" : "false";
@@ -167,15 +205,16 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
     }
 
     /**
-     * Whether to disable the OpenAPI entirely. Once the OpenAPI has been disabled then it cannot be
-     * enabled later at runtime.
+     * Whether to disable the OpenAPI entirely. Once the OpenAPI has been disabled then it cannot be enabled later at
+     * runtime.
      */
     public OpenApiDefinition disabled() {
         return disabled(true);
     }
 
     /**
-     * Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.
+     * Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding
+     * route.
      */
     public OpenApiDefinition missingOperation(String missingOperation) {
         this.missingOperation = missingOperation;
@@ -183,8 +222,8 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
     }
 
     /**
-     * Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern.
-     * Multiple patterns can be specified separated by comma.
+     * Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple
+     * patterns can be specified separated by comma.
      */
     public OpenApiDefinition mockIncludePattern(String mockIncludePattern) {
         this.mockIncludePattern = mockIncludePattern;
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
index f5d30621789..326e207d299 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
@@ -761,8 +761,8 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
      * The Camel endpoint this REST service will call, such as a direct endpoint to link to an existing route that
      * handles this REST call.
      *
-     * @param uri the uri of the endpoint
-     * @return this builder
+     * @param  uri the uri of the endpoint
+     * @return     this builder
      */
     public RestDefinition to(String uri) {
         // add to last verb
@@ -868,7 +868,8 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
             addRouteDefinition(camelContext, filter, answer, config.getComponent(), config.getProducerComponent());
         }
         if (openApi != null) {
-            addRouteDefinition(camelContext, openApi, answer, config.getComponent(), config.getProducerComponent(), config.getApiContextPath());
+            addRouteDefinition(camelContext, openApi, answer, config.getComponent(), config.getProducerComponent(),
+                    config.getApiContextPath());
         }
 
         return answer;
@@ -1007,15 +1008,8 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
         if (binding.getProduces() != null) {
             options.put("produces", binding.getProduces());
         }
-        if (component != null && !component.isEmpty()) {
-            options.put("consumerComponentName", component);
-        }
-        if (producerComponent != null && !producerComponent.isEmpty()) {
-            options.put("producerComponentName", producerComponent);
-        }
-        Boolean validate = parseBoolean(camelContext, getClientRequestValidation()); // TODO: move this to open-api so its all the same place
-        if (validate != null && validate) {
-            options.put("requestValidationEnabled", "true");
+        if (openApi.getRequestValidationEnabled() != null) {
+            options.put("requestValidationEnabled", openApi.getRequestValidationEnabled());
         }
         if (openApi.getMissingOperation() != null) {
             options.put("missingOperation", openApi.getMissingOperation());
@@ -1141,7 +1135,7 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
                 // register all the default values for the query and header parameters
                 RestParamType type = param.getType();
                 if ((RestParamType.query == type || RestParamType.header == type)
-                    && ObjectHelper.isNotEmpty(param.getDefaultValue())) {
+                        && ObjectHelper.isNotEmpty(param.getDefaultValue())) {
                     binding.addDefaultValue(param.getName(), parseText(camelContext, param.getDefaultValue()));
                 }
                 // register which parameters are required
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index aaefc3d2747..8482f81acde 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -3305,6 +3305,7 @@ public class ModelParser extends BaseParser {
                 case "disabled": def.setDisabled(val); break;
                 case "missingOperation": def.setMissingOperation(val); break;
                 case "mockIncludePattern": def.setMockIncludePattern(val); break;
+                case "requestValidationEnabled": def.setRequestValidationEnabled(val); break;
                 case "routeId": def.setRouteId(val); break;
                 case "specification": def.setSpecification(val); break;
                 default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index b2d94894bf5..3c7bc4cce1b 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -4424,6 +4424,7 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("routeId", def.getRouteId());
         doWriteAttribute("specification", def.getSpecification());
         doWriteAttribute("disabled", def.getDisabled());
+        doWriteAttribute("requestValidationEnabled", def.getRequestValidationEnabled());
         doWriteElement("apiContextPath", def.getApiContextPath(), this::doWriteString);
         endElement(name);
     }
diff --git a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index eecb2246f2d..2228cd84047 100644
--- a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++ b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -4424,6 +4424,7 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("routeId", def.getRouteId());
         doWriteAttribute("specification", def.getSpecification());
         doWriteAttribute("disabled", def.getDisabled());
+        doWriteAttribute("requestValidationEnabled", def.getRequestValidationEnabled());
         doWriteElement("apiContextPath", def.getApiContextPath(), this::doWriteString);
         endElement(name);
     }


(camel) 26/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit d9567498d425ca11a37bfa706f45eb0a89ff6158
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 06:17:16 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../org/apache/camel/catalog/components/rest-openapi.json     |  4 ++--
 .../org/apache/camel/component/rest/openapi/rest-openapi.json |  4 ++--
 .../rest/openapi/DefaultRestOpenapiProcessorStrategy.java     | 11 +++++++++--
 .../camel/component/rest/openapi/RestOpenApiComponent.java    |  4 ++--
 .../camel/component/rest/openapi/RestOpenApiEndpoint.java     |  2 +-
 .../endpoint/dsl/RestOpenApiEndpointBuilderFactory.java       |  2 +-
 .../src/main/java/org/apache/camel/main/KameletMain.java      |  1 +
 7 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index aefaf840aac..a2f378c6e67 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -30,7 +30,7 @@
     "bridgeErrorHandler": { "index": 4, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
     "missingOperation": { "index": 5, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
     "consumerComponentName": { "index": 6, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "mockIncludePattern": { "index": 7, "kind": "property", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/*", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separ [...]
+    "mockIncludePattern": { "index": 7, "kind": "property", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sepa [...]
     "restOpenapiProcessorStrategy": { "index": 8, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
     "host": { "index": 9, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
     "lazyStartProducer": { "index": 10, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fai [...]
@@ -50,7 +50,7 @@
     "consumerComponentName": { "index": 5, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
     "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
     "exchangePattern": { "index": 7, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
-    "mockIncludePattern": { "index": 8, "kind": "parameter", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/*", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sepa [...]
+    "mockIncludePattern": { "index": 8, "kind": "parameter", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sep [...]
     "restOpenapiProcessorStrategy": { "index": 9, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
     "basePath": { "index": 10, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
     "consumes": { "index": 11, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index aefaf840aac..a2f378c6e67 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -30,7 +30,7 @@
     "bridgeErrorHandler": { "index": 4, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
     "missingOperation": { "index": 5, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
     "consumerComponentName": { "index": 6, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "mockIncludePattern": { "index": 7, "kind": "property", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/*", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separ [...]
+    "mockIncludePattern": { "index": 7, "kind": "property", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sepa [...]
     "restOpenapiProcessorStrategy": { "index": 8, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
     "host": { "index": 9, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
     "lazyStartProducer": { "index": 10, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fai [...]
@@ -50,7 +50,7 @@
     "consumerComponentName": { "index": 5, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
     "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
     "exchangePattern": { "index": 7, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
-    "mockIncludePattern": { "index": 8, "kind": "parameter", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/*", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sepa [...]
+    "mockIncludePattern": { "index": 8, "kind": "parameter", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sep [...]
     "restOpenapiProcessorStrategy": { "index": 9, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
     "basePath": { "index": 10, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
     "consumes": { "index": 11, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index 2659e57880e..4d1640e569a 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -124,6 +124,8 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         final PackageScanResourceResolver resolver = PluginHelper.getPackageScanResourceResolver(camelContext);
         final String[] includes = mockIncludePattern != null ? mockIncludePattern.split(",") : null;
 
+        boolean json = false;
+        boolean xml = false;
         Resource found = null;
         if (includes != null) {
             Collection<Resource> accepted = new ArrayList<>();
@@ -135,8 +137,6 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
                 }
             }
 
-            boolean json = false;
-            boolean xml = false;
             String ct = ExchangeHelper.getContentType(exchange);
             if (ct != null) {
                 json = ct.contains("json");
@@ -151,6 +151,8 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
                 boolean matchExt = !json && !xml || json && onlyExt.equals("json") || xml && onlyExt.equals("xml");
                 if (match && matchExt) {
                     found = resource;
+                    json = onlyExt.equals("json");
+                    xml = onlyExt.equals("xml");
                     break;
                 }
             }
@@ -158,6 +160,11 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         if (found != null) {
             try {
                 // use the mock data as response
+                if (json) {
+                    exchange.getMessage().setHeader(Exchange.CONTENT_TYPE, "application/json");
+                } else if (xml) {
+                    exchange.getMessage().setHeader(Exchange.CONTENT_TYPE, "text/xml");
+                }
                 exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 200);
                 exchange.getMessage().setBody(IOHelper.loadText(found.getInputStream()));
             } catch (Exception e) {
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index cefe8244e4a..fc69ee65ecf 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -135,8 +135,8 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
     private String missingOperation;
     @Metadata(description = "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern."
                             + " Multiple patterns can be specified separated by comma.",
-              label = "consumer,advanced", defaultValue = "classpath:camel-mock/*")
-    private String mockIncludePattern = "classpath:camel-mock/*";
+              label = "consumer,advanced", defaultValue = "classpath:camel-mock/**")
+    private String mockIncludePattern = "classpath:camel-mock/**";
     @Metadata(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
     private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
     @Metadata(description = "Enable usage of global SSL context parameters.", label = "security")
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 8852e838f1b..d01aba71ec7 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -171,7 +171,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     private String missingOperation;
     @UriParam(description = "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern."
                             + " Multiple patterns can be specified separated by comma.",
-              label = "consumer,advanced", defaultValue = "classpath:camel-mock/*")
+              label = "consumer,advanced", defaultValue = "classpath:camel-mock/**")
     private String mockIncludePattern;
 
     public RestOpenApiEndpoint() {
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
index 6df772e3026..e53f317f27b 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
@@ -258,7 +258,7 @@ public interface RestOpenApiEndpointBuilderFactory {
          * 
          * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
          * 
-         * Default: classpath:camel-mock/*
+         * Default: classpath:camel-mock/**
          * Group: consumer (advanced)
          * 
          * @param mockIncludePattern the value to set
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index 349f8a2b6bc..6dd0937661d 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -766,6 +766,7 @@ public class KameletMain extends MainCommandLineSupport {
         addInitialProperty("camel.component.rest-api.consumerComponentName", "platform-http");
         addInitialProperty("camel.component.rest.consumerComponentName", "platform-http");
         addInitialProperty("camel.component.rest.producerComponentName", "vertx-http");
+        addInitialProperty("camel.component.rest-openapi.mockIncludePattern", "file:camel-mock/**,classpath:camel-mock/**");
     }
 
     protected String startupInfo() {


(camel) 30/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 9356982806e90aaade3e85d52be036df7155491b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 10:00:21 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../DefaultRestOpenapiProcessorStrategy.java        | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index 2f4c9eaa996..0ac3b7de488 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -23,6 +23,7 @@ import java.util.stream.Collectors;
 
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.media.Content;
 import joptsimple.internal.Strings;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.AsyncProducer;
@@ -112,7 +113,25 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
                         .map(Enum::name)
                         .sorted()
                         .collect(Collectors.toList()), ",");
-                phc.addHttpEndpoint(uri, verbs, null, null, null);
+                String consumes = null;
+                String produces = null;
+                for (var o : p.getValue().readOperations()) {
+                    if (o.getRequestBody() != null) {
+                        Content c = o.getRequestBody().getContent();
+                        if (c != null) {
+                            consumes = Strings.join(c.keySet().stream().sorted().collect(Collectors.toList()), ",");
+                        }
+                    }
+                    if (o.getResponses() != null) {
+                        for (var a : o.getResponses().values()) {
+                            Content c = a.getContent();
+                            if (c != null) {
+                                produces = Strings.join(c.keySet().stream().sorted().collect(Collectors.toList()), ",");
+                            }
+                        }
+                    }
+                }
+                phc.addHttpEndpoint(uri, verbs, consumes, produces, null);
                 uris.add(uri);
             }
         }


(camel) 36/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 1e994ed9ac5b7c8c8824c68e30cea76ba87447b8
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 17:43:36 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc b/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc
index 2e577c202e9..0a195bfe40b 100644
--- a/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc
+++ b/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc
@@ -121,8 +121,3 @@ YAML::
 ----
 ====
 
-
-== Client Request Validation
-
-TODO: Does not yet work
-


(camel) 22/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit d2f1e31090ec671521906c48cf37acc86344d8f0
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 17:00:52 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../camel/catalog/components/rest-openapi.json     | 38 ++++++++++++----------
 .../dsl/RestOpenApiEndpointBuilderFactory.java     | 18 ++++++++++
 .../camel/kotlin/components/RestOpenapiUriDsl.kt   |  8 +++++
 3 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index e4b0b0ac3fb..aefaf840aac 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -30,15 +30,16 @@
     "bridgeErrorHandler": { "index": 4, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
     "missingOperation": { "index": 5, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
     "consumerComponentName": { "index": 6, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
-    "restOpenapiProcessorStrategy": { "index": 7, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "host": { "index": 8, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 9, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "componentName": { "index": 10, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
-    "consumes": { "index": 11, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
-    "produces": { "index": 12, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
-    "autowiredEnabled": { "index": 13, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
-    "sslContextParameters": { "index": 14, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
-    "useGlobalSslContextParameters": { "index": 15, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
+    "mockIncludePattern": { "index": 7, "kind": "property", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/*", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separ [...]
+    "restOpenapiProcessorStrategy": { "index": 8, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "host": { "index": 9, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 10, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fai [...]
+    "componentName": { "index": 11, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
+    "consumes": { "index": 12, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the va [...]
+    "produces": { "index": 13, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi s [...]
+    "autowiredEnabled": { "index": 14, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
+    "sslContextParameters": { "index": 15, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
+    "useGlobalSslContextParameters": { "index": 16, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
@@ -49,14 +50,15 @@
     "consumerComponentName": { "index": 5, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
     "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
     "exchangePattern": { "index": 7, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
-    "restOpenapiProcessorStrategy": { "index": 8, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
-    "basePath": { "index": 9, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "consumes": { "index": 10, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
-    "host": { "index": 11, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
-    "produces": { "index": 12, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
-    "componentName": { "index": 13, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
-    "lazyStartProducer": { "index": 14, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
-    "requestValidationCustomizer": { "index": 15, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
-    "requestValidationLevels": { "index": 16, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
+    "mockIncludePattern": { "index": 8, "kind": "parameter", "displayName": "Mock Include Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/*", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified sepa [...]
+    "restOpenapiProcessorStrategy": { "index": 9, "kind": "parameter", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
+    "basePath": { "index": 10, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
+    "consumes": { "index": 11, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP  [...]
+    "host": { "index": 12, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a n [...]
+    "produces": { "index": 13, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
+    "componentName": { "index": 14, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
+    "lazyStartProducer": { "index": 15, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "requestValidationCustomizer": { "index": 16, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
+    "requestValidationLevels": { "index": 17, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
index 78546192e62..6df772e3026 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
@@ -251,6 +251,24 @@ public interface RestOpenApiEndpointBuilderFactory {
             doSetProperty("exchangePattern", exchangePattern);
             return this;
         }
+        /**
+         * Used for inclusive filtering of mock data from directories. The
+         * pattern is using Ant-path style pattern. Multiple patterns can be
+         * specified separated by comma.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Default: classpath:camel-mock/*
+         * Group: consumer (advanced)
+         * 
+         * @param mockIncludePattern the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointConsumerBuilder mockIncludePattern(
+                String mockIncludePattern) {
+            doSetProperty("mockIncludePattern", mockIncludePattern);
+            return this;
+        }
         /**
          * To use a custom strategy for how to process Rest DSL requests.
          * 
diff --git a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
index a4e550f2223..038f1cc4836 100644
--- a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
+++ b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
@@ -147,6 +147,14 @@ public class RestOpenapiUriDsl(
     it.property("exchangePattern", exchangePattern)
   }
 
+  /**
+   * Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style
+   * pattern. Multiple patterns can be specified separated by comma.
+   */
+  public fun mockIncludePattern(mockIncludePattern: String) {
+    it.property("mockIncludePattern", mockIncludePattern)
+  }
+
   /**
    * To use a custom strategy for how to process Rest DSL requests
    */


(camel) 29/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit a32952c631a4aed00709409bc4eaddd8c2eb5957
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 09:46:49 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 components/camel-rest-openapi/pom.xml              |  4 ++
 .../DefaultRestOpenapiProcessorStrategy.java       | 27 ++++++++++++
 .../rest/openapi/RestOpenApiEndpoint.java          | 48 ++--------------------
 .../component/rest/openapi/RestOpenApiHelper.java  | 44 ++++++++++++++++++++
 .../rest/openapi/RestOpenApiProcessor.java         | 15 ++-----
 5 files changed, 82 insertions(+), 56 deletions(-)

diff --git a/components/camel-rest-openapi/pom.xml b/components/camel-rest-openapi/pom.xml
index 47b7d883b14..26decde74ba 100644
--- a/components/camel-rest-openapi/pom.xml
+++ b/components/camel-rest-openapi/pom.xml
@@ -48,6 +48,10 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-rest</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-platform-http</artifactId>
+        </dependency>
 
          <dependency>
             <groupId>io.swagger.core.v3</groupId>
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index 4d1640e569a..2f4c9eaa996 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -23,6 +23,7 @@ import java.util.stream.Collectors;
 
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
+import joptsimple.internal.Strings;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.AsyncProducer;
 import org.apache.camel.CamelContext;
@@ -32,6 +33,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.NonManagedService;
 import org.apache.camel.Route;
 import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.platform.http.PlatformHttpComponent;
 import org.apache.camel.spi.PackageScanResourceResolver;
 import org.apache.camel.spi.ProducerCache;
 import org.apache.camel.spi.Resource;
@@ -58,6 +60,7 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
     private String component = "direct";
     private String missingOperation;
     private String mockIncludePattern;
+    private final List<String> uris = new ArrayList<>();
 
     @Override
     public void validateOpenApi(OpenAPI openAPI) throws Exception {
@@ -95,6 +98,24 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
                 LOG.debug(msg + ". This validation error is ignored (Will return a mocked/empty response).");
             }
         }
+
+        // enlist open-api rest services
+        PlatformHttpComponent phc = camelContext.getComponent("platform-http", PlatformHttpComponent.class);
+        if (phc != null) {
+            String path = RestOpenApiHelper.getBasePathFromOpenApi(openAPI);
+            if (path == null || path.isEmpty() || path.equals("/")) {
+                path = "";
+            }
+            for (var p : openAPI.getPaths().entrySet()) {
+                String uri = path + p.getKey();
+                String verbs = Strings.join(p.getValue().readOperationsMap().keySet().stream()
+                        .map(Enum::name)
+                        .sorted()
+                        .collect(Collectors.toList()), ",");
+                phc.addHttpEndpoint(uri, verbs, null, null, null);
+                uris.add(uri);
+            }
+        }
     }
 
     @Override
@@ -236,6 +257,12 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
     @Override
     protected void doStop() throws Exception {
         ServiceHelper.stopService(producerCache);
+
+        PlatformHttpComponent phc = camelContext.getComponent("platform-http", PlatformHttpComponent.class);
+        if (phc != null) {
+            uris.forEach(phc::removeHttpEndpoint);
+            uris.clear();
+        }
     }
 
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index d01aba71ec7..0ef9aa3703e 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -30,8 +30,6 @@ import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -213,7 +211,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     public Consumer createConsumer(final Processor processor) throws Exception {
         OpenAPI doc = loadSpecificationFrom(getCamelContext(), specificationUri);
         String path = determineBasePath(doc);
-        Processor target = new RestOpenApiProcessor(this, doc, path, processor);
+        Processor target = new RestOpenApiProcessor(this, doc, path, processor, restOpenapiProcessorStrategy);
         CamelContextAware.trySetCamelContext(target, getCamelContext());
         return createConsumerFor(path, target);
     }
@@ -510,7 +508,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
             return componentBasePath;
         }
 
-        final String specificationBasePath = getBasePathFromOpenApi(openapi);
+        final String specificationBasePath = RestOpenApiHelper.getBasePathFromOpenApi(openapi);
 
         if (isNotEmpty(specificationBasePath)) {
             return specificationBasePath;
@@ -528,46 +526,6 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         return RestOpenApiComponent.DEFAULT_BASE_PATH;
     }
 
-    public static String getBasePathFromOpenApi(final OpenAPI openApi) {
-        String basePath = null;
-        if (openApi.getServers() != null) {
-            for (Server server : openApi.getServers()) {
-                if (server.getUrl() != null) {
-                    try {
-                        URI serverUrl = new URI(parseVariables(server.getUrl(), server));
-                        basePath = serverUrl.getPath();
-                        // Is this really necessary?
-                        if (basePath.indexOf("//") == 0) {
-                            // strip off the first "/" if double "/" exists
-                            basePath = basePath.substring(1);
-                        }
-                        if ("/".equals(basePath)) {
-                            basePath = "";
-                        }
-                    } catch (URISyntaxException e) {
-                        //not a valid whole url, just the basePath
-                        basePath = server.getUrl();
-                    }
-                }
-            }
-        }
-        return basePath;
-    }
-
-    public static String parseVariables(String url, Server server) {
-        Pattern p = Pattern.compile("\\{(.*?)\\}");
-        Matcher m = p.matcher(url);
-        while (m.find()) {
-
-            String variable = m.group(1);
-            if (server != null && server.getVariables() != null && server.getVariables().get(variable) != null) {
-                String varValue = server.getVariables().get(variable).getDefault();
-                url = url.replace("{" + variable + "}", varValue);
-            }
-        }
-        return url;
-    }
-
     String determineComponentName() {
         return Optional.ofNullable(componentName).orElse(getComponent().getComponentName());
     }
@@ -753,7 +711,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         if (servers != null) {
             for (Server server : servers) {
                 try {
-                    uris.add(new URI(parseVariables(server.getUrl(), server)));
+                    uris.add(new URI(RestOpenApiHelper.parseVariables(server.getUrl(), server)));
                 } catch (URISyntaxException e) {
                     // ignore
                 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiHelper.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiHelper.java
index 4af6a0772c8..fc8e460c551 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiHelper.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiHelper.java
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.component.rest.openapi;
 
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
@@ -23,6 +25,8 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.servers.Server;
 import org.apache.camel.spi.ContentTypeAware;
 import org.apache.camel.spi.Resource;
 import org.apache.camel.util.ObjectHelper;
@@ -90,4 +94,44 @@ final class RestOpenApiHelper {
         return location.toLowerCase().endsWith(".yml") || location.toLowerCase().endsWith(".yaml");
     }
 
+    public static String getBasePathFromOpenApi(final OpenAPI openApi) {
+        String basePath = null;
+        if (openApi.getServers() != null) {
+            for (Server server : openApi.getServers()) {
+                if (server.getUrl() != null) {
+                    try {
+                        URI serverUrl = new URI(parseVariables(server.getUrl(), server));
+                        basePath = serverUrl.getPath();
+                        // Is this really necessary?
+                        if (basePath.indexOf("//") == 0) {
+                            // strip off the first "/" if double "/" exists
+                            basePath = basePath.substring(1);
+                        }
+                        if ("/".equals(basePath)) {
+                            basePath = "";
+                        }
+                    } catch (URISyntaxException e) {
+                        //not a valid whole url, just the basePath
+                        basePath = server.getUrl();
+                    }
+                }
+            }
+        }
+        return basePath;
+    }
+
+    public static String parseVariables(String url, Server server) {
+        Pattern p = Pattern.compile("\\{(.*?)\\}");
+        Matcher m = p.matcher(url);
+        while (m.find()) {
+
+            String variable = m.group(1);
+            if (server != null && server.getVariables() != null && server.getVariables().get(variable) != null) {
+                String varValue = server.getVariables().get(variable).getDefault();
+                url = url.replace("{" + variable + "}", varValue);
+            }
+        }
+        return url;
+    }
+
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index 35aa33035f2..429b01dcd4b 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -48,14 +48,15 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
     private final OpenAPI openAPI;
     private final String basePath;
     private final List<RestConsumerContextPathMatcher.ConsumerPath<Operation>> paths = new ArrayList<>();
-    private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy;
+    private final RestOpenapiProcessorStrategy restOpenapiProcessorStrategy;
 
-    public RestOpenApiProcessor(RestOpenApiEndpoint endpoint, OpenAPI openAPI, String basePath, Processor processor) {
+    public RestOpenApiProcessor(RestOpenApiEndpoint endpoint, OpenAPI openAPI, String basePath, Processor processor,
+                                RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) {
         super(processor);
         this.endpoint = endpoint;
         this.basePath = basePath;
         this.openAPI = openAPI;
-        this.restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
+        this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy;
     }
 
     @Override
@@ -68,14 +69,6 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
         this.camelContext = camelContext;
     }
 
-    public RestOpenapiProcessorStrategy getRestOpenapiProcessorStrategy() {
-        return restOpenapiProcessorStrategy;
-    }
-
-    public void setRestOpenapiProcessorStrategy(RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) {
-        this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy;
-    }
-
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
         String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);


(camel) 05/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 00b95c8a944b25fbcf0fe474aed57e2881c85064
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Mar 24 13:45:49 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../rest/openapi/RestOpenApiEndpoint.java          | 11 ++------
 .../rest/openapi/RestOpenApiProcessor.java         | 33 ++++++++++++++++++++++
 2 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 1fd6f314adc..4e54d21cd7f 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -195,14 +195,9 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
 
     @Override
     public Consumer createConsumer(final Processor processor) throws Exception {
-        final CamelContext camelContext = getCamelContext();
-        final OpenAPI openapiDoc = loadSpecificationFrom(camelContext, specificationUri);
-        String path = determineBasePath(openapiDoc);
-
-        // TODO: processor should use OpenAPI to detect which operations exists, and map to direct:xx
-        // TODO: validate on|poff
-
-        return createConsumerFor(path, processor);
+        OpenAPI doc = loadSpecificationFrom(getCamelContext(), specificationUri);
+        String path = determineBasePath(doc);
+        return createConsumerFor(path, new RestOpenApiProcessor(doc, path, processor));
     }
 
     protected Consumer createConsumerFor(String basePath, Processor processor) throws Exception {
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
new file mode 100644
index 00000000000..737f14c2643
--- /dev/null
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -0,0 +1,33 @@
+/*
+ * 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.apache.camel.component.rest.openapi;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import org.apache.camel.Processor;
+import org.apache.camel.support.processor.DelegateAsyncProcessor;
+
+public class RestOpenApiProcessor extends DelegateAsyncProcessor {
+
+    private final OpenAPI openAPI;
+    private final String basePath;
+
+    public RestOpenApiProcessor(OpenAPI openAPI, String basePath, Processor processor) {
+        super(processor);
+        this.basePath = basePath;
+        this.openAPI = openAPI;
+    }
+}


(camel) 02/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f16ac201f93820edf222cfdd9f21551ed94d96d5
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Mar 24 12:19:57 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../component/rest/openapi/RestOpenApiEndpoint.java | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 0bd4ca6a251..bb80f463521 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -175,6 +175,11 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         setExchangePattern(ExchangePattern.InOut);
     }
 
+    @Override
+    public RestOpenApiComponent getComponent() {
+        return (RestOpenApiComponent) super.getComponent();
+    }
+
     @Override
     public Consumer createConsumer(final Processor processor) throws Exception {
         throw new UnsupportedOperationException("Consumer not supported");
@@ -310,10 +315,6 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         return requestValidationLevels;
     }
 
-    RestOpenApiComponent component() {
-        return (RestOpenApiComponent) getComponent();
-    }
-
     Producer createProducerFor(
             final OpenAPI openapi, final Operation operation, final String method,
             final String uriTemplate)
@@ -334,7 +335,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         // let the rest endpoint configure itself
         endpoint.configureProperties(params);
 
-        RestOpenApiComponent component = component();
+        RestOpenApiComponent component = getComponent();
         RequestValidator requestValidator = null;
         if (component.isRequestValidationEnabled() || requestValidationEnabled) {
             requestValidator = configureRequestValidator(openapi, operation, method, uriTemplate);
@@ -350,7 +351,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
             return basePath;
         }
 
-        final String componentBasePath = component().getBasePath();
+        final String componentBasePath = getComponent().getBasePath();
         if (isNotEmpty(componentBasePath)) {
             return componentBasePath;
         }
@@ -414,7 +415,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     }
 
     String determineComponentName() {
-        return Optional.ofNullable(componentName).orElse(component().getComponentName());
+        return Optional.ofNullable(componentName).orElse(getComponent().getComponentName());
     }
 
     Map<String, Object> determineEndpointParameters(final OpenAPI openapi, final Operation operation) {
@@ -430,7 +431,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
             parameters.put("host", host);
         }
 
-        final RestOpenApiComponent component = component();
+        final RestOpenApiComponent component = getComponent();
 
         // what we consume is what the API defined by OpenApi specification
         // produces
@@ -520,7 +521,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
             return host;
         }
 
-        final String componentHost = component().getHost();
+        final String componentHost = getComponent().getHost();
         if (isNotEmpty(componentHost)) {
             return componentHost;
         }
@@ -672,7 +673,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     }
 
     RequestValidator configureRequestValidator(OpenAPI openapi, Operation operation, String method, String uriTemplate) {
-        RestOpenApiComponent component = component();
+        RestOpenApiComponent component = getComponent();
         RequestValidationCustomizer validationCustomizer = requestValidationCustomizer;
         if (validationCustomizer == null) {
             validationCustomizer = component.getRequestValidationCustomizer();


(camel) 14/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit bcd4534903ced30e334ba235ce9883c2afbc8c52
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 10:37:12 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../component/rest/openapi/RestOpenApiComponent.java   |  3 ++-
 .../component/rest/openapi/RestOpenApiEndpoint.java    | 18 +++---------------
 .../component/rest/openapi/RestOpenApiProcessor.java   | 10 ++++++++++
 .../rest/openapi/RestOpenApiRequestValidationTest.java |  3 +--
 4 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index eef794e5371..b405b1466c5 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
 import org.apache.camel.SSLContextParametersAware;
+import org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer;
 import org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.RestProducerFactory;
@@ -133,7 +134,7 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
     @Metadata(description = "If request validation is enabled, this option provides the capability to customize"
                             + " the creation of OpenApiInteractionValidator used to validate requests.",
               label = "advanced")
-    private RequestValidationCustomizer requestValidationCustomizer;
+    private RequestValidationCustomizer requestValidationCustomizer = new DefaultRequestValidationCustomizer();
     @Metadata(description = "Enable usage of global SSL context parameters.", label = "security")
     private boolean useGlobalSslContextParameters;
     @Metadata(description = "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context ",
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 21fde6f5618..034a7e3e56b 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -62,7 +62,6 @@ import org.apache.camel.ExchangePattern;
 import org.apache.camel.NoSuchBeanException;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
-import org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer;
 import org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer;
 import org.apache.camel.component.rest.openapi.validator.RequestValidator;
 import org.apache.camel.component.rest.openapi.validator.RestOpenApiOperation;
@@ -468,9 +467,8 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         // let the rest endpoint configure itself
         endpoint.configureProperties(params);
 
-        RestOpenApiComponent component = getComponent();
         RequestValidator requestValidator = null;
-        if (component.isRequestValidationEnabled() || requestValidationEnabled) {
+        if (requestValidationEnabled) {
             requestValidator = configureRequestValidator(openapi, operation, method, uriTemplate);
         }
 
@@ -810,16 +808,6 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     }
 
     RequestValidator configureRequestValidator(OpenAPI openapi, Operation operation, String method, String uriTemplate) {
-        RestOpenApiComponent component = getComponent();
-        RequestValidationCustomizer validationCustomizer = requestValidationCustomizer;
-        if (validationCustomizer == null) {
-            validationCustomizer = component.getRequestValidationCustomizer();
-        }
-
-        if (validationCustomizer == null) {
-            validationCustomizer = new DefaultRequestValidationCustomizer();
-        }
-
         RestOpenApiOperation restOpenApiOperation = new RestOpenApiOperation(operation, method, uriTemplate);
         OpenApiInteractionValidator.Builder builder = OpenApiInteractionValidator.createFor(openapi);
 
@@ -837,9 +825,9 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         });
         builder.withLevelResolver(levelResolverBuilder.build());
 
-        validationCustomizer.customizeOpenApiInteractionValidator(builder);
+        requestValidationCustomizer.customizeOpenApiInteractionValidator(builder);
 
-        return new RequestValidator(builder.build(), restOpenApiOperation, validationCustomizer);
+        return new RequestValidator(builder.build(), restOpenApiOperation, requestValidationCustomizer);
     }
 
     static String determineOption(
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index 4cfbccc1839..5e3291d82c9 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -27,6 +27,7 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
+import org.apache.camel.component.rest.openapi.validator.RequestValidator;
 import org.apache.camel.support.RestConsumerContextPathMatcher;
 import org.apache.camel.support.processor.DelegateAsyncProcessor;
 import org.apache.camel.support.service.ServiceHelper;
@@ -41,6 +42,7 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
     private final String basePath;
     private final List<RestConsumerContextPathMatcher.ConsumerPath<Operation>> paths = new ArrayList<>();
     private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy;
+    private RequestValidator requestValidator;
 
     public RestOpenApiProcessor(OpenAPI openAPI, String basePath, Processor processor) {
         super(processor);
@@ -67,6 +69,14 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
         this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy;
     }
 
+    public RequestValidator getRequestValidator() {
+        return requestValidator;
+    }
+
+    public void setRequestValidator(RequestValidator requestValidator) {
+        this.requestValidator = requestValidator;
+    }
+
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
         // TODO: RequestValidator
diff --git a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiRequestValidationTest.java b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiRequestValidationTest.java
index 82593e6c461..cf2cf854e58 100644
--- a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiRequestValidationTest.java
+++ b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiRequestValidationTest.java
@@ -68,7 +68,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class RestOpenApiRequestValidationTest extends CamelTestSupport {
@@ -362,7 +361,7 @@ public class RestOpenApiRequestValidationTest extends CamelTestSupport {
         RestOpenApiEndpoint endpoint = context.getEndpoint(petStoreVersion + ":#addPet", RestOpenApiEndpoint.class);
         endpoint.createProducer();
         assertFalse(endpoint.isRequestValidationEnabled());
-        assertNull(endpoint.getRequestValidationCustomizer());
+        assertNotNull(endpoint.getRequestValidationCustomizer());
         assertTrue(endpoint.getRequestValidationLevels().isEmpty());
     }
 


(camel) 31/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 4d00975a471709b0e3a63d7520c0d0fae697b054
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 10:19:51 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../platform/http/PlatformHttpComponent.java          | 12 +++++++-----
 .../component/platform/http/PlatformHttpConsumer.java | 19 ++++++++++++++++---
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java
index 7dfa58a4d02..5e8b15740ef 100644
--- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java
+++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java
@@ -90,7 +90,7 @@ public class PlatformHttpComponent extends DefaultComponent
         // reuse the createConsumer method we already have. The api need to use GET and match on uri prefix
         return doCreateConsumer(camelContext, processor, "GET", contextPath, null, null, "application/json,text/yaml",
                 configuration,
-                parameters, true);
+                parameters, true, true);
     }
 
     @Override
@@ -100,7 +100,7 @@ public class PlatformHttpComponent extends DefaultComponent
             String consumes, String produces, RestConfiguration configuration, Map<String, Object> parameters)
             throws Exception {
         return doCreateConsumer(camelContext, processor, verb, basePath, uriTemplate, consumes, produces, configuration,
-                parameters, false);
+                parameters, false, true);
     }
 
     @Override
@@ -109,7 +109,7 @@ public class PlatformHttpComponent extends DefaultComponent
             Map<String, Object> parameters)
             throws Exception {
         return doCreateConsumer(camelContext, processor, null, contextPath, null, null, null, configuration,
-                parameters, true);
+                parameters, true, false);
     }
 
     /**
@@ -196,7 +196,8 @@ public class PlatformHttpComponent extends DefaultComponent
     private Consumer doCreateConsumer(
             CamelContext camelContext, Processor processor, String verb, String basePath,
             String uriTemplate,
-            String consumes, String produces, RestConfiguration configuration, Map<String, Object> parameters, boolean api)
+            String consumes, String produces, RestConfiguration configuration, Map<String, Object> parameters,
+            boolean api, boolean register)
             throws Exception {
 
         String path = basePath;
@@ -246,7 +247,8 @@ public class PlatformHttpComponent extends DefaultComponent
         endpoint.setProduces(produces);
 
         // configure consumer properties
-        Consumer consumer = endpoint.createConsumer(processor);
+        PlatformHttpConsumer consumer = (PlatformHttpConsumer) endpoint.createConsumer(processor);
+        consumer.setRegister(register);
         if (config.getConsumerProperties() != null && !config.getConsumerProperties().isEmpty()) {
             setProperties(camelContext, consumer, config.getConsumerProperties());
         }
diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpConsumer.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpConsumer.java
index 5fb01bf62f1..c2020081876 100644
--- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpConsumer.java
+++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpConsumer.java
@@ -27,6 +27,7 @@ import org.apache.camel.support.service.ServiceHelper;
 public class PlatformHttpConsumer extends DefaultConsumer implements Suspendable, SuspendableService {
 
     private Consumer delegatedConsumer;
+    private boolean register = true;
 
     public PlatformHttpConsumer(Endpoint endpoint, Processor processor) {
         super(endpoint, processor);
@@ -41,6 +42,14 @@ public class PlatformHttpConsumer extends DefaultConsumer implements Suspendable
         return getEndpoint().getComponent();
     }
 
+    public boolean isRegister() {
+        return register;
+    }
+
+    public void setRegister(boolean register) {
+        this.register = register;
+    }
+
     @Override
     protected void doInit() throws Exception {
         super.doInit();
@@ -51,14 +60,18 @@ public class PlatformHttpConsumer extends DefaultConsumer implements Suspendable
     protected void doStart() throws Exception {
         super.doStart();
         ServiceHelper.startService(delegatedConsumer);
-        getComponent().addHttpEndpoint(getEndpoint().getPath(), getEndpoint().getHttpMethodRestrict(),
-                getEndpoint().getConsumes(), getEndpoint().getProduces(), delegatedConsumer);
+        if (register) {
+            getComponent().addHttpEndpoint(getEndpoint().getPath(), getEndpoint().getHttpMethodRestrict(),
+                    getEndpoint().getConsumes(), getEndpoint().getProduces(), delegatedConsumer);
+        }
     }
 
     @Override
     protected void doStop() throws Exception {
         super.doStop();
-        getComponent().removeHttpEndpoint(getEndpoint().getPath());
+        if (register) {
+            getComponent().removeHttpEndpoint(getEndpoint().getPath());
+        }
         ServiceHelper.stopAndShutdownServices(delegatedConsumer);
     }
 


(camel) 16/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit d1b3aed8b0673b1046ca39871366767852c11b4e
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 11:01:51 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java   | 2 --
 1 file changed, 2 deletions(-)

diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index b1000f26ccc..39184eecadf 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -78,8 +78,6 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
 
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
-        // TODO: binding
-
         String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);
         if (path != null && path.startsWith(basePath)) {
             path = path.substring(basePath.length());


(camel) 35/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 0a2c51b7cbdd73da6c0ed58fec714367c139bf4c
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 17:43:19 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../working-with-camel-core/pages/index.adoc       |   1 +
 docs/user-manual/modules/ROOT/nav.adoc             |   1 +
 docs/user-manual/modules/ROOT/pages/dsl.adoc       |   1 +
 docs/user-manual/modules/ROOT/pages/index.adoc     |   1 +
 .../modules/ROOT/pages/rest-dsl-openapi.adoc       | 128 +++++++++++++++++++++
 docs/user-manual/modules/ROOT/pages/rest-dsl.adoc  |   4 +
 6 files changed, 136 insertions(+)

diff --git a/docs/main/modules/working-with-camel-core/pages/index.adoc b/docs/main/modules/working-with-camel-core/pages/index.adoc
index 5d7409a0bd0..d1bcda18e29 100644
--- a/docs/main/modules/working-with-camel-core/pages/index.adoc
+++ b/docs/main/modules/working-with-camel-core/pages/index.adoc
@@ -100,6 +100,7 @@ Learn about additional ways to customize your integrations. Explore alternatives
 ** xref:manual::property-binding.adoc[Property Binding]
 ** xref:manual::registry.adoc[Registry]
 ** xref:manual::rest-dsl.adoc[Rest DSL]
+** xref:manual::rest-dsl-openapi.adoc[Rest DSL contract first with OpenAPI]
 ** xref:manual::route-configuration.adoc[Route Configuration]
 ** xref:manual::service-registry.adoc[Service Registry]
 ** xref:manual::spring.adoc[Spring]
diff --git a/docs/user-manual/modules/ROOT/nav.adoc b/docs/user-manual/modules/ROOT/nav.adoc
index d83bce43922..b7413027ae3 100644
--- a/docs/user-manual/modules/ROOT/nav.adoc
+++ b/docs/user-manual/modules/ROOT/nav.adoc
@@ -25,6 +25,7 @@
 *** xref:notify-builder.adoc[NotifyBuilder]
 *** xref:advice-with.adoc[AdviceWith]
 ** xref:rest-dsl.adoc[Working with REST and Rest DSL]
+*** xref:rest-dsl-openapi.adoc[Rest DSL contract first]
 ** xref:writing-components.adoc[Writing Components]
 ** xref:release-guide.adoc[Release guide]
 *** xref:release-guide-website.adoc[Adding doc versions to the website]
diff --git a/docs/user-manual/modules/ROOT/pages/dsl.adoc b/docs/user-manual/modules/ROOT/pages/dsl.adoc
index 609dc0f3cf5..01d7db85190 100644
--- a/docs/user-manual/modules/ROOT/pages/dsl.adoc
+++ b/docs/user-manual/modules/ROOT/pages/dsl.adoc
@@ -10,6 +10,7 @@ languages (DSL) as listed below:
 * xref:components::spring-summary.adoc[Spring XML] - A XML based DSL in classic Spring XML files.
 * xref:components:others:yaml-dsl.adoc[Yaml DSL] for creating routes using YAML format.
 * xref:rest-dsl.adoc[Rest DSL] - A DSL to define REST services using REST verbs.
+** xref:rest-dsl-openapi.adoc[Rest DSL contract first] - Rest DSL using _contract first_ when OpenAPI specs.
 * xref:components:others:groovy-dsl.adoc[Groovy DSL] - A Groovy-based DSL to create routes leveraging closures and a specific Groovy extension module.
 * xref:components:others:kotlin-dsl.adoc[Kotlin DSL] - A Kotlin-based DSL.
 * xref:bean-integration.adoc[Annotation DSL] - Use annotations in Java beans.
diff --git a/docs/user-manual/modules/ROOT/pages/index.adoc b/docs/user-manual/modules/ROOT/pages/index.adoc
index 99c372f0ac0..7bc73e2fb4d 100644
--- a/docs/user-manual/modules/ROOT/pages/index.adoc
+++ b/docs/user-manual/modules/ROOT/pages/index.adoc
@@ -62,6 +62,7 @@ For a deeper and better understanding of Apache Camel, an xref:faq:what-is-camel
 * xref:camel-maven-archetypes.adoc[Camel Maven Archetypes]
 * xref:components::jmx-component.adoc[Camel JMX]
 * xref:rest-dsl.adoc[Working with REST and Rest DSL]
+** xref:rest-dsl-openapi.adoc[Rest DSL contract first with OpenAPI]
 * xref:writing-components.adoc[Writing Custom Camel Components]
 
 === xref:architecture.adoc[Architecture]
diff --git a/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc b/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc
new file mode 100644
index 00000000000..2e577c202e9
--- /dev/null
+++ b/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc
@@ -0,0 +1,128 @@
+= REST DSL with contract first OpenAPI
+
+From *Camel 4.6* onwards the xref:rest-dsl.adoc[Rest DSL] has been improved with a _contract first_
+approach using vanilla OpenAPI specification.
+
+== How it works
+
+The Rest DSL OpenAPI is a facade that builds xref:components::rest-openapi-component.adoc[Rest OpenAPI] endpoint as
+consumer for Camel routes. The actual HTTP transport is leveraged by using the xref:components::platform-http-component.adoc[Platform HTTP],
+which makes it plugin to Camel Spring Boot, Camel Quarkus or can run standalone with Camel Main.
+
+== Contract first
+
+The _contract first_ approach requires you to have an existing OpenAPI v3 specification file.
+This contract is a standard OpenAPI contract, and you can use any existing API design tool to build such contracts.
+
+TIP: Camel support OpenAPI v3.0 and v3.1.
+
+In Camel, you then use the Rest DSL in _contract first_ mode. For example having a contracted in a file named `my-contract.json`,
+you can then copy this file to `src/main/resources` so its loaded from classpath.
+
+In Camel Rest DSL you can then very easily define _contract first_ as shown below:
+
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+@Override
+public void configure() throws Exception {
+    rest().openApi("petstore-v3.json");
+}
+----
+XML::
++
+[source,xml]
+----
+<rest>
+  <openApi specification="petstore-v3.json"/>
+</rest>
+----
+YAML::
++
+[source,yaml]
+----
+- rest:
+    openApi:
+      specification: petstore-v3.json
+----
+====
+
+When Camel startup the OpenAPI specification file is loaded and parsed. For every APIs
+Camel builds HTTP REST endpoint, which are routed 1:1 to Camel routes using the `direct:operationId` naming convention.
+
+The _pestore_ has 18 APIs here we look at the 5 user APIs:
+
+[source,text]
+----
+ http://0.0.0.0:8080/api/v3/user                       (POST)   (accept:application/json,application/x-www-form-urlencoded,application/xml produce:application/json,application/xml)
+ http://0.0.0.0:8080/api/v3/user/createWithList        (POST)   (accept:application/json produce:application/json,application/xml)
+ http://0.0.0.0:8080/api/v3/user/login                 (GET)    (produce:application/json,application/xml)
+ http://0.0.0.0:8080/api/v3/user/logout                (GET)
+ http://0.0.0.0:8080/api/v3/user/{username}            (DELETE,GET,PUT)
+----
+
+These APIs are outputted using the URI that clients can use to call the service.
+Each of these APIs has a unique _operation id_ which is what Camel uses for calling the route. This gives:
+
+[source,text]
+----
+ http://0.0.0.0:8080/api/v3/user                       direct:createUser
+ http://0.0.0.0:8080/api/v3/user/createWithList        direct:createUsersWithListInput
+ http://0.0.0.0:8080/api/v3/user/login                 direct:loginUser
+ http://0.0.0.0:8080/api/v3/user/logout                direct:logoutUser
+ http://0.0.0.0:8080/api/v3/user/{username}            direct:getUserByName
+----
+
+You should then implement a route for each API that starts from those direct endpoints listed above, such as:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+@Override
+public void configure() throws Exception {
+    rest().openApi("petstore-v3.json");
+
+    from("direct:getUserByName")
+       ... // do something here
+}
+----
+XML::
++
+[source,xml]
+----
+<rest>
+  <openApi specification="petstore-v3.json"/>
+</rest>
+<route>
+  <from uri="direct:getUserByName"/>
+  // do something here
+</route>
+----
+YAML::
++
+[source,yaml]
+----
+- rest:
+    openApi:
+      specification: petstore-v3.json
+- route:
+    from:
+      uri: direct:getUserByName
+      steps:
+        - log:
+            message: "do something here"
+----
+====
+
+
+== Client Request Validation
+
+TODO: Does not yet work
+
diff --git a/docs/user-manual/modules/ROOT/pages/rest-dsl.adoc b/docs/user-manual/modules/ROOT/pages/rest-dsl.adoc
index da30ec0b68a..07d3e87f069 100644
--- a/docs/user-manual/modules/ROOT/pages/rest-dsl.adoc
+++ b/docs/user-manual/modules/ROOT/pages/rest-dsl.adoc
@@ -5,6 +5,10 @@ Apache Camel offers a REST styled DSL.
 The intention is to allow end users to define REST services (hosted by Camel) using a
 REST style with verbs such as get, post, delete etc.
 
+NOTE: From *Camel 4.6* onwards the Rest DSL has been improved with a _contract first_ approach using vanilla OpenAPI specification
+files. This is documented in the xref:rest-dsl-openapi.adoc[Rest DSL with OpenAPI contract first] page. This current page documents the
+_code first_ Rest DSL that Camel provides for a long time.
+
 == How it works
 
 The Rest DSL is a facade that builds xref:components::rest-component.adoc[Rest] endpoints as


(camel) 32/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit e40d5caa3d5573199057070e7783c4de2a28e71b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 27 10:54:02 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../org/apache/camel/catalog/models/openApi.json   |   5 +-
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  39 +++++++-
 ...PlatformHttpRestOpenApiConsumerRestDslTest.java |  32 ++-----
 .../org/apache/camel/model/rest/openApi.json       |   5 +-
 .../apache/camel/model/rest/OpenApiDefinition.java | 106 ++++++++++++++++++++-
 .../apache/camel/model/rest/RestDefinition.java    |  31 ++++--
 .../java/org/apache/camel/xml/in/ModelParser.java  |   3 +
 .../java/org/apache/camel/xml/out/ModelWriter.java |   3 +
 .../org/apache/camel/yaml/out/ModelWriter.java     |   3 +
 .../dsl/yaml/deserializers/ModelDeserializers.java |  20 +++-
 .../generated/resources/schema/camelYamlDsl.json   |  21 +++-
 11 files changed, 231 insertions(+), 37 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json
index 2fec558b620..f1292c7c300 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/openApi.json
@@ -15,6 +15,9 @@
     "id": { "index": 0, "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
     "description": { "index": 1, "kind": "element", "displayName": "Description", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" },
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST service has been disabled then it cannot be enabled later at runtime." },
-    "specification": { "index": 3, "kind": "attribute", "displayName": "Specification", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false }
+    "specification": { "index": 3, "kind": "attribute", "displayName": "Specification", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Path to the OpenApi specification file." },
+    "routeId": { "index": 4, "kind": "attribute", "displayName": "Route Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of the route" },
+    "missingOperation": { "index": 5, "kind": "attribute", "displayName": "Missing Operation", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
+    "mockIncludePattern": { "index": 6, "kind": "attribute", "displayName": "Mock Include Pattern", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma." }
   }
 }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 53195be2296..d800a098830 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -16388,13 +16388,50 @@ The flow used by the OAuth2 security scheme. Valid values are implicit, password
     <xs:complexContent>
       <xs:extension base="tns:optionalIdentifiedDefinition">
         <xs:sequence/>
-        <xs:attribute name="specification" type="xs:string" use="required"/>
+        <xs:attribute name="specification" type="xs:string" use="required">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Path to the OpenApi specification file.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="routeId" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Sets the id of the route.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
         <xs:attribute name="disabled" type="xs:string">
           <xs:annotation>
             <xs:documentation xml:lang="en">
 <![CDATA[
 Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST
 service has been disabled then it cannot be enabled later at runtime. Default value: false
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="missingOperation" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.
+Default value: fail
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="mockIncludePattern" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple
+patterns can be specified separated by comma. Default value: classpath:camel-mock/**
 ]]>
             </xs:documentation>
           </xs:annotation>
diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
index f91954d1ceb..db51da21007 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
@@ -18,7 +18,6 @@ package org.apache.camel.component.platform.http.vertx;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.rest.openapi.RestOpenApiComponent;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -37,10 +36,7 @@ public class PlatformHttpRestOpenApiConsumerRestDslTest {
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() {
-                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
-                    c.setMissingOperation("ignore");
-
-                    rest().openApi("openapi-v3.json");
+                    rest().openApi().specification("openapi-v3.json").missingOperation("ignore");
 
                     from("direct:getPetById")
                             .setBody().constant("{\"pet\": \"tony the tiger\"}");
@@ -99,10 +95,7 @@ public class PlatformHttpRestOpenApiConsumerRestDslTest {
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() {
-                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
-                    c.setMissingOperation("mock");
-
-                    rest().openApi("openapi-v3.json");
+                    rest().openApi().specification("openapi-v3.json").missingOperation("mock");
 
                     from("direct:getPetById")
                             .setBody().constant("{\"pet\": \"tony the tiger\"}");
@@ -163,10 +156,7 @@ public class PlatformHttpRestOpenApiConsumerRestDslTest {
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() {
-                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
-                    c.setMissingOperation("ignore");
-
-                    rest().openApi("openapi-v3.json");
+                    rest().openApi().specification("openapi-v3.json").missingOperation("ignore");
 
                     from("direct:getPetById")
                             .setBody().constant("{\"pet\": \"tony the tiger\"}");
@@ -193,10 +183,7 @@ public class PlatformHttpRestOpenApiConsumerRestDslTest {
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() {
-                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
-                    c.setMissingOperation("ignore");
-
-                    rest().openApi("openapi-v3.json");
+                    rest().openApi().specification("openapi-v3.json").missingOperation("ignore");
 
                     from("direct:getPetById")
                             .setBody().constant("{\"pet\": \"tony the tiger\"}");
@@ -223,10 +210,8 @@ public class PlatformHttpRestOpenApiConsumerRestDslTest {
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() {
-                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
-                    c.setMissingOperation("ignore");
-
-                    rest().clientRequestValidation(true).openApi("openapi-v3.json");
+                    rest().clientRequestValidation(true)
+                            .openApi().specification("openapi-v3.json").missingOperation("ignore");
 
                     from("direct:updatePet")
                             .setBody().constant("{\"pet\": \"tony the tiger\"}");
@@ -253,10 +238,7 @@ public class PlatformHttpRestOpenApiConsumerRestDslTest {
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() {
-                    RestOpenApiComponent c = context.getComponent("rest-openapi", RestOpenApiComponent.class);
-                    c.setMissingOperation("mock");
-
-                    rest().openApi("openapi-v3.json");
+                    rest().openApi().specification("openapi-v3.json").missingOperation("mock");
                 }
             });
 
diff --git a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json
index 2fec558b620..f1292c7c300 100644
--- a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json
+++ b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/rest/openApi.json
@@ -15,6 +15,9 @@
     "id": { "index": 0, "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
     "description": { "index": 1, "kind": "element", "displayName": "Description", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" },
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST service has been disabled then it cannot be enabled later at runtime." },
-    "specification": { "index": 3, "kind": "attribute", "displayName": "Specification", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false }
+    "specification": { "index": 3, "kind": "attribute", "displayName": "Specification", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Path to the OpenApi specification file." },
+    "routeId": { "index": 4, "kind": "attribute", "displayName": "Route Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of the route" },
+    "missingOperation": { "index": 5, "kind": "attribute", "displayName": "Missing Operation", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
+    "mockIncludePattern": { "index": 6, "kind": "attribute", "displayName": "Mock Include Pattern", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "classpath:camel-mock\/**", "description": "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma." }
   }
 }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
index f2d34c56d81..1eefdff7728 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/OpenApiDefinition.java
@@ -39,8 +39,20 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
     @XmlAttribute(required = true)
     private String specification;
     @XmlAttribute
+    private String routeId;
+    @XmlAttribute
     @Metadata(label = "advanced", javaType = "java.lang.Boolean")
     private String disabled;
+    @XmlAttribute
+    @Metadata(enums = "fail,ignore,mock", defaultValue = "fail")
+    private String missingOperation;
+    @XmlAttribute
+    @Metadata(label = "advanced", defaultValue = "classpath:camel-mock/**")
+    private String mockIncludePattern;
+
+    public void setRest(RestDefinition rest) {
+        this.rest = rest;
+    }
 
     @Override
     public String getShortName() {
@@ -72,11 +84,103 @@ public class OpenApiDefinition extends OptionalIdentifiedDefinition<OpenApiDefin
         this.disabled = disabled;
     }
 
+    public String getMissingOperation() {
+        return missingOperation;
+    }
+
+    /**
+     * Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.
+     */
+    public void setMissingOperation(String missingOperation) {
+        this.missingOperation = missingOperation;
+    }
+
+    public String getMockIncludePattern() {
+        return mockIncludePattern;
+    }
+
+    /**
+     * Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern.
+     * Multiple patterns can be specified separated by comma.
+     */
+    public void setMockIncludePattern(String mockIncludePattern) {
+        this.mockIncludePattern = mockIncludePattern;
+    }
+
+    public String getRouteId() {
+        return routeId;
+    }
+
+    /**
+     * Sets the id of the route
+     */
+    public void setRouteId(String routeId) {
+        this.routeId = routeId;
+    }
+
     // Fluent API
     // -------------------------------------------------------------------------
 
-    public RestDefinition specification(String specification) {
+    /**
+     * Path to the OpenApi specification file.
+     */
+    public OpenApiDefinition specification(String specification) {
         this.specification = specification;
+        return this;
+    }
+
+    /**
+     * Whether to disable the OpenAPI entirely. Once the OpenAPI has been disabled then it cannot be
+     * enabled later at runtime.
+     */
+    public OpenApiDefinition disabled(String disabled) {
+        this.disabled = disabled;
+        return this;
+    }
+
+    /**
+     * Whether to disable the OpenAPI entirely. Once the OpenAPI has been disabled then it cannot be
+     * enabled later at runtime.
+     */
+    public OpenApiDefinition disabled(boolean disabled) {
+        this.disabled = disabled ? "true" : "false";
+        return this;
+    }
+
+    /**
+     * Whether to disable the OpenAPI entirely. Once the OpenAPI has been disabled then it cannot be
+     * enabled later at runtime.
+     */
+    public OpenApiDefinition disabled() {
+        return disabled(true);
+    }
+
+    /**
+     * Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.
+     */
+    public OpenApiDefinition missingOperation(String missingOperation) {
+        this.missingOperation = missingOperation;
+        return this;
+    }
+
+    /**
+     * Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern.
+     * Multiple patterns can be specified separated by comma.
+     */
+    public OpenApiDefinition mockIncludePattern(String mockIncludePattern) {
+        this.mockIncludePattern = mockIncludePattern;
+        return this;
+    }
+
+    /**
+     * Sets the id of the route
+     */
+    public OpenApiDefinition routeId(String routeId) {
+        this.routeId = routeId;
+        return this;
+    }
+
+    public RestDefinition end() {
         return rest;
     }
 
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
index 379d5f46cde..6f1406b8caf 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
@@ -238,7 +238,7 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
 
     /**
      * Whether to enable validation of the client request to check:
-     *
+     * <p>
      * 1) Content-Type header matches what the Rest DSL consumes; returns HTTP Status 415 if validation error. 2) Accept
      * header matches what the Rest DSL produces; returns HTTP Status 406 if validation error. 3) Missing required data
      * (query parameters, HTTP headers, body); returns HTTP Status 400 if validation error. 4) Parsing error of the
@@ -311,12 +311,23 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
     // Fluent API
     // -------------------------------------------------------------------------
 
+    /**
+     * To use an existing OpenAPI specification as contract-first for Camel Rest DSL.
+     */
+    public OpenApiDefinition openApi() {
+        openApi = new OpenApiDefinition();
+        openApi.setRest(this);
+        return openApi;
+    }
+
     /**
      * To use an existing OpenAPI specification as contract-first for Camel Rest DSL.
      */
     public RestDefinition openApi(String specification) {
         openApi = new OpenApiDefinition();
-        return openApi.specification(specification);
+        openApi.setRest(this);
+        openApi.specification(specification);
+        return this;
     }
 
     /**
@@ -750,8 +761,8 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
      * The Camel endpoint this REST service will call, such as a direct endpoint to link to an existing route that
      * handles this REST call.
      *
-     * @param  uri the uri of the endpoint
-     * @return     this builder
+     * @param uri the uri of the endpoint
+     * @return this builder
      */
     public RestDefinition to(String uri) {
         // add to last verb
@@ -961,6 +972,9 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
             String component, String producerComponent) {
 
         RouteDefinition route = new RouteDefinition();
+        if (openApi.getRouteId() != null) {
+            route.routeId(parseText(camelContext, openApi.getRouteId()));
+        }
         // add dummy empty stop
         route.getOutputs().add(new StopDefinition());
 
@@ -983,7 +997,6 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
         binding.setClientRequestValidation(getClientRequestValidation());
         binding.setEnableCORS(getEnableCORS());
         binding.setEnableNoContentResponse(getEnableNoContentResponse());
-
         route.setRestBindingDefinition(binding);
 
         // append options
@@ -1004,6 +1017,12 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
         if (validate != null && validate) {
             options.put("requestValidationEnabled", "true");
         }
+        if (openApi.getMissingOperation() != null) {
+            options.put("missingOperation", openApi.getMissingOperation());
+        }
+        if (openApi.getMockIncludePattern() != null) {
+            options.put("mockIncludePattern", openApi.getMockIncludePattern());
+        }
 
         // include optional description
         String description = openApi.getDescription();
@@ -1119,7 +1138,7 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition>
                 // register all the default values for the query and header parameters
                 RestParamType type = param.getType();
                 if ((RestParamType.query == type || RestParamType.header == type)
-                        && ObjectHelper.isNotEmpty(param.getDefaultValue())) {
+                    && ObjectHelper.isNotEmpty(param.getDefaultValue())) {
                     binding.addDefaultValue(param.getName(), parseText(camelContext, param.getDefaultValue()));
                 }
                 // register which parameters are required
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index 754fdcd576c..3d97bfcbcbb 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -3303,6 +3303,9 @@ public class ModelParser extends BaseParser {
         return doParse(new OpenApiDefinition(), (def, key, val) -> {
             switch (key) {
                 case "disabled": def.setDisabled(val); break;
+                case "missingOperation": def.setMissingOperation(val); break;
+                case "mockIncludePattern": def.setMockIncludePattern(val); break;
+                case "routeId": def.setRouteId(val); break;
                 case "specification": def.setSpecification(val); break;
                 default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
             }
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index 86c297846c1..c889b477c4f 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -4419,6 +4419,9 @@ public class ModelWriter extends BaseWriter {
             throws IOException {
         startElement(name);
         doWriteOptionalIdentifiedDefinitionAttributes(def);
+        doWriteAttribute("mockIncludePattern", def.getMockIncludePattern());
+        doWriteAttribute("missingOperation", def.getMissingOperation());
+        doWriteAttribute("routeId", def.getRouteId());
         doWriteAttribute("specification", def.getSpecification());
         doWriteAttribute("disabled", def.getDisabled());
         endElement(name);
diff --git a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index 00ba07c5722..4630515246d 100644
--- a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++ b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -4419,6 +4419,9 @@ public class ModelWriter extends BaseWriter {
             throws IOException {
         startElement(name);
         doWriteOptionalIdentifiedDefinitionAttributes(def);
+        doWriteAttribute("mockIncludePattern", def.getMockIncludePattern());
+        doWriteAttribute("missingOperation", def.getMissingOperation());
+        doWriteAttribute("routeId", def.getRouteId());
         doWriteAttribute("specification", def.getSpecification());
         doWriteAttribute("disabled", def.getDisabled());
         endElement(name);
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index 2080a28405f..3aaddb6953b 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -10360,7 +10360,10 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "description", type = "string", description = "Sets the description of this node", displayName = "Description"),
                     @YamlProperty(name = "disabled", type = "boolean", description = "Whether to disable all the REST services from the OpenAPI contract from the route during build time. Once an REST service has been disabled then it cannot be enabled later at runtime.", displayName = "Disabled"),
                     @YamlProperty(name = "id", type = "string", description = "Sets the id of this node", displayName = "Id"),
-                    @YamlProperty(name = "specification", type = "string", required = true, displayName = "Specification")
+                    @YamlProperty(name = "missingOperation", type = "enum:fail,ignore,mock", defaultValue = "fail", description = "Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.", displayName = "Missing Operation"),
+                    @YamlProperty(name = "mockIncludePattern", type = "string", defaultValue = "classpath:camel-mock/**", description = "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma.", displayName = "Mock Include Pattern"),
+                    @YamlProperty(name = "routeId", type = "string", description = "Sets the id of the route", displayName = "Route Id"),
+                    @YamlProperty(name = "specification", type = "string", required = true, description = "Path to the OpenApi specification file.", displayName = "Specification")
             }
     )
     public static class OpenApiDefinitionDeserializer extends YamlDeserializerBase<OpenApiDefinition> {
@@ -10383,6 +10386,21 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setDisabled(val);
                     break;
                 }
+                case "missingOperation": {
+                    String val = asText(node);
+                    target.setMissingOperation(val);
+                    break;
+                }
+                case "mockIncludePattern": {
+                    String val = asText(node);
+                    target.setMockIncludePattern(val);
+                    break;
+                }
+                case "routeId": {
+                    String val = asText(node);
+                    target.setRouteId(val);
+                    break;
+                }
                 case "specification": {
                     String val = asText(node);
                     target.setSpecification(val);
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index 00d55240b25..06660fe71d7 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -14689,9 +14689,28 @@
             "title" : "Id",
             "description" : "Sets the id of this node"
           },
+          "missingOperation" : {
+            "type" : "string",
+            "title" : "Missing Operation",
+            "description" : "Whether to fail, ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.",
+            "default" : "fail",
+            "enum" : [ "fail", "ignore", "mock" ]
+          },
+          "mockIncludePattern" : {
+            "type" : "string",
+            "title" : "Mock Include Pattern",
+            "description" : "Used for inclusive filtering of mock data from directories. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma.",
+            "default" : "classpath:camel-mock/**"
+          },
+          "routeId" : {
+            "type" : "string",
+            "title" : "Route Id",
+            "description" : "Sets the id of the route"
+          },
           "specification" : {
             "type" : "string",
-            "title" : "Specification"
+            "title" : "Specification",
+            "description" : "Path to the OpenApi specification file."
           }
         },
         "required" : [ "specification" ]


(camel) 08/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 443af94082bac115cde67d5e6356f065bb1684fe
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Mar 24 15:37:52 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../rest/openapi/RestOpenApiEndpoint.java          |  5 +-
 .../rest/openapi/RestOpenApiProcessor.java         | 63 ++++++++++++++++++++--
 2 files changed, 63 insertions(+), 5 deletions(-)

diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index c65a309d923..c6b8eca82f9 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -53,6 +53,7 @@ import io.swagger.v3.oas.models.servers.Server;
 import io.swagger.v3.parser.core.models.ParseOptions;
 import io.swagger.v3.parser.core.models.SwaggerParseResult;
 import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
 import org.apache.camel.Category;
 import org.apache.camel.Component;
 import org.apache.camel.Consumer;
@@ -208,7 +209,9 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     public Consumer createConsumer(final Processor processor) throws Exception {
         OpenAPI doc = loadSpecificationFrom(getCamelContext(), specificationUri);
         String path = determineBasePath(doc);
-        return createConsumerFor(path, new RestOpenApiProcessor(doc, path, processor));
+        Processor target = new RestOpenApiProcessor(doc, path, processor);
+        CamelContextAware.trySetCamelContext(target, getCamelContext());
+        return createConsumerFor(path, target);
     }
 
     protected Consumer createConsumerFor(String basePath, Processor processor) throws Exception {
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index 98409220064..bc9767eaadd 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -18,14 +18,23 @@ package org.apache.camel.component.rest.openapi;
 
 import io.swagger.v3.oas.models.OpenAPI;
 import org.apache.camel.AsyncCallback;
+import org.apache.camel.AsyncProducer;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
+import org.apache.camel.spi.ProducerCache;
+import org.apache.camel.support.cache.DefaultProducerCache;
 import org.apache.camel.support.processor.DelegateAsyncProcessor;
+import org.apache.camel.support.service.ServiceHelper;
 
-public class RestOpenApiProcessor extends DelegateAsyncProcessor {
+public class RestOpenApiProcessor extends DelegateAsyncProcessor implements CamelContextAware {
 
+    private CamelContext camelContext;
     private final OpenAPI openAPI;
     private final String basePath;
+    private ProducerCache producerCache;
 
     public RestOpenApiProcessor(OpenAPI openAPI, String basePath, Processor processor) {
         super(processor);
@@ -33,10 +42,56 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor {
         this.openAPI = openAPI;
     }
 
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
-        // what operation to invoke
-        exchange.getMessage().setBody("I was here");
-        return super.process(exchange, callback);
+        String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);
+        if (path != null && path.startsWith(basePath)) {
+            path = path.substring(basePath.length() + 1);
+        }
+
+        // TODO: choose processor strategy (mapping by operation id -> direct)
+        // TODO: check if valid operation according to OpenApi
+        // TODO: validate GET/POST etc
+        // TODO: 404 and so on
+        // TODO: binding
+
+        Endpoint e = camelContext.getEndpoint("direct:" + path);
+        AsyncProducer p = producerCache.acquireProducer(e);
+        return p.process(exchange, new AsyncCallback() {
+            @Override
+            public void done(boolean doneSync) {
+                producerCache.releaseProducer(e, p);
+                callback.done(doneSync);
+            }
+        });
+    }
+
+    @Override
+    protected void doInit() throws Exception {
+        super.doInit();
+        producerCache = new DefaultProducerCache(this, getCamelContext(), 1000);
+        ServiceHelper.initService(producerCache);
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+        ServiceHelper.startService(producerCache);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        super.doStop();
+        ServiceHelper.stopService(producerCache);
     }
 }


(camel) 06/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit bed697b46fd8b63f41210442a52d1130e533dd95
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Mar 24 13:53:44 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../component/platform/http/PlatformHttpComponent.java | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java
index d57d96a76f1..7dfa58a4d02 100644
--- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java
+++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java
@@ -34,6 +34,7 @@ import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.RestApiConsumerFactory;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.RestConsumerFactory;
+import org.apache.camel.spi.RestOpenApiConsumerFactory;
 import org.apache.camel.spi.annotations.Component;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.DefaultComponent;
@@ -48,7 +49,8 @@ import org.slf4j.LoggerFactory;
  * Exposes HTTP endpoints leveraging the given platform's (SpringBoot, WildFly, Quarkus, ...) HTTP server.
  */
 @Component("platform-http")
-public class PlatformHttpComponent extends DefaultComponent implements RestConsumerFactory, RestApiConsumerFactory {
+public class PlatformHttpComponent extends DefaultComponent
+        implements RestConsumerFactory, RestApiConsumerFactory, RestOpenApiConsumerFactory {
 
     private static final Logger LOG = LoggerFactory.getLogger(PlatformHttpComponent.class);
 
@@ -101,6 +103,15 @@ public class PlatformHttpComponent extends DefaultComponent implements RestConsu
                 parameters, false);
     }
 
+    @Override
+    public Consumer createConsumer(
+            CamelContext camelContext, Processor processor, String contextPath, RestConfiguration configuration,
+            Map<String, Object> parameters)
+            throws Exception {
+        return doCreateConsumer(camelContext, processor, null, contextPath, null, null, null, configuration,
+                parameters, true);
+    }
+
     /**
      * Adds a known http endpoint managed by this component.
      */
@@ -224,8 +235,9 @@ public class PlatformHttpComponent extends DefaultComponent implements RestConsu
         if (api) {
             map.put("matchOnUriPrefix", "true");
         }
-
-        RestComponentHelper.addHttpRestrictParam(map, verb, cors);
+        if (verb != null) {
+            RestComponentHelper.addHttpRestrictParam(map, verb, cors);
+        }
 
         String url = RestComponentHelper.createRestConsumerUrl("platform-http", path, map);
 


(camel) 38/38: Merge branch 'openapi' into openapi2

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f832211747971567e6d800b8beeec5a152b3341f
Merge: 69b850bf7bf cf2d5d01329
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Mar 28 15:32:57 2024 +0100

    Merge branch 'openapi' into openapi2

 .../camel/catalog/components/platform-http.json    |    4 +-
 .../camel/catalog/components/rest-openapi.json     |   62 +-
 .../org/apache/camel/catalog/models.properties     |    1 +
 .../org/apache/camel/catalog/models/openApi.json   |   24 +
 .../org/apache/camel/catalog/models/rest.json      |    5 +-
 .../camel/catalog/models/restConfiguration.json    |    2 +-
 .../apache/camel/catalog/schemas/camel-spring.xsd  |   81 +-
 components/camel-platform-http-vertx/pom.xml       |    5 +
 ...PlatformHttpRestOpenApiConsumerRestDslTest.java |  307 +++++
 .../vertx/PlatformHttpRestOpenApiConsumerTest.java |  270 +++++
 .../src/test/resources/camel-mock/pet/444.json     |    3 +
 .../src/test/resources/openapi-v3.json             | 1240 ++++++++++++++++++++
 .../component/platform/http/platform-http.json     |    4 +-
 .../platform/http/PlatformHttpComponent.java       |   28 +-
 .../platform/http/PlatformHttpConsumer.java        |   19 +-
 .../platform/http/PlatformHttpEndpoint.java        |   10 +-
 components/camel-rest-openapi/pom.xml              |    4 +
 .../openapi/RestOpenApiComponentConfigurer.java    |   40 +-
 .../openapi/RestOpenApiEndpointConfigurer.java     |   48 +
 .../openapi/RestOpenApiEndpointUriFactory.java     |   12 +-
 .../camel/component/rest/openapi/rest-openapi.json |   62 +-
 .../src/main/docs/rest-openapi-component.adoc      |    4 +-
 .../DefaultRestOpenapiProcessorStrategy.java       |  319 +++++
 .../rest/openapi/RestOpenApiComponent.java         |  153 ++-
 .../rest/openapi/RestOpenApiConsumerPath.java      |   53 +
 .../rest/openapi/RestOpenApiEndpoint.java          |  392 ++++---
 .../component/rest/openapi/RestOpenApiHelper.java  |   44 +
 .../rest/openapi/RestOpenApiProcessor.java         |  181 +++
 .../rest/openapi/RestOpenapiProcessorStrategy.java |   89 ++
 .../validator/RequestValidationCustomizer.java     |    1 +
 .../rest/openapi/validator/RequestValidator.java   |   31 +-
 .../camel/component/rest/openapi/HttpsV3Test.java  |    3 +-
 .../rest/openapi/RestOpenApiComponentV3Test.java   |    6 +-
 .../openapi/RestOpenApiComponentV3YamlTest.java    |    7 +-
 .../RestOpenApiCustomValidatorCustomizerTest.java  |    3 +-
 .../rest/openapi/RestOpenApiEndpointV3Test.java    |    8 +-
 .../openapi/RestOpenApiRequestValidationTest.java  |    6 +-
 .../camel/component/rest/DefaultRestRegistry.java  |    2 +-
 .../apache/camel/spi/RestApiConsumerFactory.java   |   14 +-
 .../org/apache/camel/spi/RestConsumerFactory.java  |    1 +
 ...actory.java => RestOpenApiConsumerFactory.java} |   20 +-
 .../org/apache/camel/model/rest/openApi.json       |   24 +
 .../META-INF/org/apache/camel/model/rest/rest.json |    5 +-
 .../apache/camel/model/rest/restConfiguration.json |    2 +-
 .../services/org/apache/camel/model.properties     |    1 +
 .../org/apache/camel/model/rest/jaxb.index         |    1 +
 .../apache/camel/model/rest/OpenApiDefinition.java |  245 ++++
 .../model/rest/RestConfigurationDefinition.java    |    4 +-
 .../apache/camel/model/rest/RestDefinition.java    |  143 ++-
 .../main/support/MockRestConsumerFactory.java      |    4 +
 .../java/org/apache/camel/xml/in/ModelParser.java  |   21 +
 .../java/org/apache/camel/xml/out/ModelWriter.java |   20 +
 .../org/apache/camel/yaml/out/ModelWriter.java     |   20 +
 .../working-with-camel-core/pages/index.adoc       |    1 +
 docs/user-manual/modules/ROOT/nav.adoc             |    1 +
 .../ROOT/pages/camel-4x-upgrade-guide-4_6.adoc     |    7 +-
 docs/user-manual/modules/ROOT/pages/dsl.adoc       |    1 +
 docs/user-manual/modules/ROOT/pages/index.adoc     |    1 +
 .../modules/ROOT/pages/rest-dsl-openapi.adoc       |  123 ++
 docs/user-manual/modules/ROOT/pages/rest-dsl.adoc  |    4 +
 .../dsl/RestOpenapiComponentBuilderFactory.java    |  238 ++--
 .../src/generated/resources/metadata.json          |    2 +-
 .../builder/endpoint/StaticEndpointBuilders.java   |   10 +-
 .../dsl/PlatformHttpEndpointBuilderFactory.java    |   32 +-
 .../dsl/RestOpenApiEndpointBuilderFactory.java     |  704 +++++++++--
 .../java/org/apache/camel/main/KameletMain.java    |    8 +-
 .../camel/kotlin/components/RestOpenapiUriDsl.kt   |  164 ++-
 .../dsl/yaml/deserializers/ModelDeserializers.java |   93 +-
 .../deserializers/ModelDeserializersResolver.java  |    3 +
 .../generated/resources/schema/camelYamlDsl.json   |   59 +-
 70 files changed, 4923 insertions(+), 586 deletions(-)

diff --cc docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_6.adoc
index 360199e51bb,27d2fe89a48..878af534033
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_6.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_6.adoc
@@@ -15,6 -15,8 +15,11 @@@ then the variable is no longer set. Als
  
  This is the same logic that the routing engine uses, whether to continue routing the `Exchange` or not.
  
 +=== camel-elasticsearch
 +
- The class `org.apache.camel.component.es.aggregation.ElastichsearchBulkRequestAggregationStrategy` has been renamed to `org.apache.camel.component.es.aggregation.ElasticsearchBulkRequestAggregationStrategy`.
++The class `org.apache.camel.component.es.aggregation.ElastichsearchBulkRequestAggregationStrategy` has been renamed to `org.apache.camel.component.es.aggregation.ElasticsearchBulkRequestAggregationStrategy`.
++
+ === camel-rest-openapi
+ 
+ The `specifciationUri` in the `rest-api` component has changed from being a `java.net.URI` to a `String` type
+ , as it uses Camels `ResourceLoader` to load from pluggable resources and also more tooling friendly.
 -


(camel) 25/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit b5304ef3b49a69f384fe2443b2112636f8eb7fae
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Mar 26 10:47:10 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../main/java/org/apache/camel/component/rest/DefaultRestRegistry.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/components/camel-rest/src/main/java/org/apache/camel/component/rest/DefaultRestRegistry.java b/components/camel-rest/src/main/java/org/apache/camel/component/rest/DefaultRestRegistry.java
index 5efa6ef7064..0e2f28d12bb 100644
--- a/components/camel-rest/src/main/java/org/apache/camel/component/rest/DefaultRestRegistry.java
+++ b/components/camel-rest/src/main/java/org/apache/camel/component/rest/DefaultRestRegistry.java
@@ -98,7 +98,7 @@ public class DefaultRestRegistry extends ServiceSupport implements StaticService
                             ? config.getApiComponent() : RestApiEndpoint.DEFAULT_API_COMPONENT_NAME;
                     String path = config.getApiContextPath() != null ? config.getApiContextPath() : "api-doc";
                     String uri = String.format(
-                            "rest-api:%s/%s?componentName=%s&apiComponentName=%s&contextIdPattern=#name#",
+                            "rest-api:%s/%s?componentName=%s&apiComponentName=%s",
                             path, camelContext.getName(), componentName, apiComponent);
 
                     restApiEndpoint = camelContext.getEndpoint(uri);


(camel) 01/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit ea8682c1e77c8d3c7ac1f33dcfed3f423c7f9ace
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Mar 24 11:56:41 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../camel/catalog/components/rest-openapi.json     |  34 ++--
 .../camel/component/rest/openapi/rest-openapi.json |  34 ++--
 .../rest/openapi/RestOpenApiComponent.java         |  49 ++---
 .../rest/openapi/RestOpenApiEndpoint.java          |  35 ++--
 .../org/apache/camel/spi/RestConsumerFactory.java  |   1 +
 ...actory.java => RestOpenApiConsumerFactory.java} |  20 +-
 .../main/support/MockRestConsumerFactory.java      |   4 +
 .../dsl/RestOpenapiComponentBuilderFactory.java    | 156 ++++++++--------
 .../dsl/RestOpenApiEndpointBuilderFactory.java     | 204 ++++++++++-----------
 9 files changed, 254 insertions(+), 283 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index 3393cc929be..9242b3b9735 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -24,15 +24,15 @@
   },
   "componentProperties": {
     "basePath": { "index": 0, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
-    "componentName": { "index": 1, "kind": "property", "displayName": "Component Name", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH is searched for sing [...]
-    "consumes": { "index": 2, "kind": "property", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP he [...]
-    "host": { "index": 3, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 4, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "produces": { "index": 5, "kind": "property", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Can be  [...]
-    "requestValidationCustomizer": { "index": 6, "kind": "property", "displayName": "Request Validation Customizer", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer", "description": "If request validation is enabled, [...]
-    "requestValidationEnabled": { "index": 7, "kind": "property", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "specificationUri": { "index": 8, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
-    "autowiredEnabled": { "index": 9, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
+    "host": { "index": 1, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "requestValidationEnabled": { "index": 3, "kind": "property", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
+    "specificationUri": { "index": 4, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
+    "componentName": { "index": 5, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
+    "consumes": { "index": 6, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
+    "produces": { "index": 7, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi sp [...]
+    "autowiredEnabled": { "index": 8, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
+    "requestValidationCustomizer": { "index": 9, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator us [...]
     "sslContextParameters": { "index": 10, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
     "useGlobalSslContextParameters": { "index": 11, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
@@ -40,13 +40,13 @@
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification." },
     "basePath": { "index": 2, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "componentName": { "index": 3, "kind": "parameter", "displayName": "Component Name", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH is searched for sin [...]
-    "consumes": { "index": 4, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
-    "host": { "index": 5, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
-    "produces": { "index": 6, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overri [...]
-    "requestValidationCustomizer": { "index": 7, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer", "description": "If request validation is enabled [...]
-    "requestValidationEnabled": { "index": 8, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "requestValidationLevels": { "index": 9, "kind": "parameter", "displayName": "Request Validation Levels", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by 'validatio [...]
-    "lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "consumes": { "index": 3, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
+    "host": { "index": 4, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
+    "produces": { "index": 5, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overri [...]
+    "requestValidationEnabled": { "index": 6, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
+    "componentName": { "index": 7, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
+    "lazyStartProducer": { "index": 8, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...]
+    "requestValidationCustomizer": { "index": 9, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
+    "requestValidationLevels": { "index": 10, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index 3393cc929be..9242b3b9735 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -24,15 +24,15 @@
   },
   "componentProperties": {
     "basePath": { "index": 0, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
-    "componentName": { "index": 1, "kind": "property", "displayName": "Component Name", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH is searched for sing [...]
-    "consumes": { "index": 2, "kind": "property", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP he [...]
-    "host": { "index": 3, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 4, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "produces": { "index": 5, "kind": "property", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Can be  [...]
-    "requestValidationCustomizer": { "index": 6, "kind": "property", "displayName": "Request Validation Customizer", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer", "description": "If request validation is enabled, [...]
-    "requestValidationEnabled": { "index": 7, "kind": "property", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "specificationUri": { "index": 8, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
-    "autowiredEnabled": { "index": 9, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
+    "host": { "index": 1, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "requestValidationEnabled": { "index": 3, "kind": "property", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
+    "specificationUri": { "index": 4, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
+    "componentName": { "index": 5, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
+    "consumes": { "index": 6, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
+    "produces": { "index": 7, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi sp [...]
+    "autowiredEnabled": { "index": 8, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
+    "requestValidationCustomizer": { "index": 9, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator us [...]
     "sslContextParameters": { "index": 10, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
     "useGlobalSslContextParameters": { "index": 11, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
@@ -40,13 +40,13 @@
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification." },
     "basePath": { "index": 2, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "componentName": { "index": 3, "kind": "parameter", "displayName": "Component Name", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH is searched for sin [...]
-    "consumes": { "index": 4, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
-    "host": { "index": 5, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
-    "produces": { "index": 6, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overri [...]
-    "requestValidationCustomizer": { "index": 7, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer", "description": "If request validation is enabled [...]
-    "requestValidationEnabled": { "index": 8, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "requestValidationLevels": { "index": 9, "kind": "parameter", "displayName": "Request Validation Levels", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by 'validatio [...]
-    "lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "consumes": { "index": 3, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
+    "host": { "index": 4, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
+    "produces": { "index": 5, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overri [...]
+    "requestValidationEnabled": { "index": 6, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
+    "componentName": { "index": 7, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
+    "lazyStartProducer": { "index": 8, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...]
+    "requestValidationCustomizer": { "index": 9, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
+    "requestValidationLevels": { "index": 10, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index a20dc157392..ec4acc1707d 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -78,32 +78,22 @@ import static org.apache.camel.util.StringHelper.notEmpty;
  */
 @Component("rest-openapi")
 public final class RestOpenApiComponent extends DefaultComponent implements SSLContextParametersAware {
+
     public static final String DEFAULT_BASE_PATH = "/";
 
     static final URI DEFAULT_SPECIFICATION_URI = URI.create(RestOpenApiComponent.DEFAULT_SPECIFICATION_URI_STR);
 
     static final String DEFAULT_SPECIFICATION_URI_STR = "openapi.json";
 
-    @Metadata(
-              description = "API basePath, for example \"`/v2`\". Default is unset, if set overrides the value present in OpenApi specification.",
-              defaultValue = "", label = "producer")
+    @Metadata(description = "API basePath, for example \"`/v2`\". Default is unset, if set overrides the value present in OpenApi specification.",
+              label = "producer")
     private String basePath = "";
-
     @Metadata(description = "Name of the Camel component that will perform the requests. The component must be present"
                             + " in Camel registry and it must implement RestProducerFactory service provider interface. If not set"
                             + " CLASSPATH is searched for single component that implements RestProducerFactory SPI. Can be overridden in"
                             + " endpoint configuration.",
-              label = "producer", required = false)
+              label = "producer,advanced")
     private String componentName;
-
-    @Metadata(
-              description = "What payload type this component capable of consuming. Could be one type, like `application/json`"
-                            + " or multiple types as `application/json, application/xml; q=0.5` according to the RFC7231. This equates"
-                            + " to the value of `Accept` HTTP header. If set overrides any value found in the OpenApi specification."
-                            + " Can be overridden in endpoint configuration",
-              label = "producer")
-    private String consumes;
-
     @Metadata(description = "Scheme hostname and port to direct the HTTP requests to in the form of"
                             + " `http[s]://hostname[:port]`. Can be configured at the endpoint, component or in the corresponding"
                             + " REST configuration in the Camel Context. If you give this component a name (e.g. `petstore`) that"
@@ -112,14 +102,17 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
                             + " configuration.",
               label = "producer")
     private String host;
-
-    @Metadata(
-              description = "What payload type this component is producing. For example `application/json`"
+    @Metadata(description = "What payload type this component capable of consuming. Could be one type, like `application/json`"
+                            + " or multiple types as `application/json, application/xml; q=0.5` according to the RFC7231. This equates"
+                            + " to the value of `Accept` HTTP header. If set overrides any value found in the OpenApi specification."
+                            + " Can be overridden in endpoint configuration",
+              label = "producer,advanced")
+    private String consumes;
+    @Metadata(description = "What payload type this component is producing. For example `application/json`"
                             + " according to the RFC7231. This equates to the value of `Content-Type` HTTP header. If set overrides"
                             + " any value present in the OpenApi specification. Can be overridden in endpoint configuration.",
-              label = "producer")
+              label = "producer,advanced")
     private String produces;
-
     @Metadata(description = "Path to the OpenApi specification file. The scheme, host base path are taken from this"
                             + " specification, but these can be overridden with properties on the component or endpoint level. If not"
                             + " given the component tries to load `openapi.json` resource. Note that the `host` defined on the"
@@ -128,24 +121,18 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
                             + " configuration.",
               defaultValue = DEFAULT_SPECIFICATION_URI_STR, label = "producer")
     private URI specificationUri;
-
-    @Metadata(description = "Customize TLS parameters used by the component. If not set defaults to the TLS parameters"
-                            + " set in the Camel context ",
-              label = "security")
-    private SSLContextParameters sslContextParameters;
-
-    @Metadata(description = "Enable usage of global SSL context parameters.", label = "security",
-              defaultValue = "false")
-    private boolean useGlobalSslContextParameters;
-
     @Metadata(description = "Enable validation of requests against the configured OpenAPI specification",
               defaultValue = "false")
     private boolean requestValidationEnabled;
-
     @Metadata(description = "If request validation is enabled, this option provides the capability to customize"
                             + " the creation of OpenApiInteractionValidator used to validate requests.",
-              defaultValue = "org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer")
+              label = "advanced")
     private RequestValidationCustomizer requestValidationCustomizer;
+    @Metadata(description = "Enable usage of global SSL context parameters.", label = "security")
+    private boolean useGlobalSslContextParameters;
+    @Metadata(description = "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context ",
+              label = "security")
+    private SSLContextParameters sslContextParameters;
 
     public RestOpenApiComponent() {
     }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index f7916a278d5..0bd4ca6a251 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -103,23 +103,14 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
 
     @UriParam(description = "API basePath, for example \"`/v3`\". Default is unset, if set overrides the value present in"
                             + " OpenApi specification and in the component configuration.",
-              defaultValue = "", label = "producer")
+              label = "producer")
     private String basePath;
-
     @UriParam(description = "Name of the Camel component that will perform the requests. The component must be present"
                             + " in Camel registry and it must implement RestProducerFactory service provider interface. If not set"
                             + " CLASSPATH is searched for single component that implements RestProducerFactory SPI. Overrides"
                             + " component configuration.",
-              label = "producer")
+              label = "producer,advanced")
     private String componentName;
-
-    @UriParam(description = "What payload type this component capable of consuming. Could be one type, like `application/json`"
-                            + " or multiple types as `application/json, application/xml; q=0.5` according to the RFC7231. This equates"
-                            + " to the value of `Accept` HTTP header. If set overrides any value found in the OpenApi specification and."
-                            + " in the component configuration",
-              label = "producer")
-    private String consumes;
-
     @UriParam(description = "Scheme hostname and port to direct the HTTP requests to in the form of"
                             + " `http[s]://hostname[:port]`. Can be configured at the endpoint, component or in the corresponding"
                             + " REST configuration in the Camel Context. If you give this component a name (e.g. `petstore`) that"
@@ -128,17 +119,20 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
                             + " configuration.",
               label = "producer")
     private String host;
-
     @UriPath(description = "ID of the operation from the OpenApi specification.", label = "producer")
     @Metadata(required = true)
     private String operationId;
-
+    @UriParam(description = "What payload type this component capable of consuming. Could be one type, like `application/json`"
+                            + " or multiple types as `application/json, application/xml; q=0.5` according to the RFC7231. This equates"
+                            + " to the value of `Accept` HTTP header. If set overrides any value found in the OpenApi specification and."
+                            + " in the component configuration",
+              label = "producer")
+    private String consumes;
     @UriParam(description = "What payload type this component is producing. For example `application/json`"
                             + " according to the RFC7231. This equates to the value of `Content-Type` HTTP header. If set overrides"
                             + " any value present in the OpenApi specification. Overrides all other configuration.",
               label = "producer")
     private String produces;
-
     @UriPath(description = "Path to the OpenApi specification file. The scheme, host base path are taken from this"
                            + " specification, but these can be overridden with properties on the component or endpoint level. If not"
                            + " given the component tries to load `openapi.json` resource from the classpath. Note that the `host` defined on the"
@@ -151,20 +145,16 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
              defaultValue = RestOpenApiComponent.DEFAULT_SPECIFICATION_URI_STR,
              defaultValueNote = "By default loads `openapi.json` file", label = "producer")
     private URI specificationUri = RestOpenApiComponent.DEFAULT_SPECIFICATION_URI;
-
-    @UriParam(description = "Enable validation of requests against the configured OpenAPI specification",
-              defaultValue = "false")
+    @UriParam(description = "Enable validation of requests against the configured OpenAPI specification")
     private boolean requestValidationEnabled;
-
     @UriParam(description = "If request validation is enabled, this option provides the capability to customize"
                             + " the creation of OpenApiInteractionValidator used to validate requests.",
-              defaultValue = "org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer")
+              label = "advanced")
     private RequestValidationCustomizer requestValidationCustomizer;
-
     @UriParam(description = "Levels for specific OpenAPI request validation options. Multiple options can be"
                             + " specified as URI options prefixed by 'validation.'. For example, validation.request.body=ERROR"
                             + "&validation.request.body.unexpected=IGNORED. Supported values are INFO, ERROR, WARN & IGNORE.",
-              prefix = "validation.", multiValue = true)
+              label = "advanced", prefix = "validation.", multiValue = true)
     private Map<String, Object> requestValidationLevels = new HashMap<>();
 
     public RestOpenApiEndpoint() {
@@ -605,8 +595,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
                 try {
                     uris.add(new URI(parseVariables(server.getUrl(), server)));
                 } catch (URISyntaxException e) {
-                    // TODO Auto-generated catch block
-                    e.printStackTrace();
+                    // ignore
                 }
             }
         }
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RestConsumerFactory.java b/core/camel-api/src/main/java/org/apache/camel/spi/RestConsumerFactory.java
index 9784bc58c4c..06ccdb8f94a 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RestConsumerFactory.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RestConsumerFactory.java
@@ -28,6 +28,7 @@ import org.apache.camel.Processor;
  * <a href="http://camel.apache.org/rest-dsl">rest-dsl</a>.
  *
  * @see RestApiConsumerFactory
+ * @see RestOpenApiConsumerFactory
  * @see RestApiProcessorFactory
  */
 public interface RestConsumerFactory {
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RestConsumerFactory.java b/core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java
similarity index 66%
copy from core/camel-api/src/main/java/org/apache/camel/spi/RestConsumerFactory.java
copy to core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java
index 9784bc58c4c..5022a1b8bf2 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RestConsumerFactory.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java
@@ -16,21 +16,22 @@
  */
 package org.apache.camel.spi;
 
-import java.util.Map;
-
 import org.apache.camel.CamelContext;
 import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
 
+import java.util.Map;
+
 /**
- * Allows SPI to plugin a {@link RestConsumerFactory} that creates the Camel {@link Consumer} responsible for handling
+ * Allows SPI to plugin a {@link RestOpenApiConsumerFactory} that creates the Camel {@link Consumer} responsible for handling
  * incoming HTTP requests from clients that request to access REST services which has been created using the
- * <a href="http://camel.apache.org/rest-dsl">rest-dsl</a>.
+ * <a href="http://camel.apache.org/rest-dsl">rest-dsl</a> for an entire open-api specification.
  *
  * @see RestApiConsumerFactory
+ * @see RestOpenApiConsumerFactory
  * @see RestApiProcessorFactory
  */
-public interface RestConsumerFactory {
+public interface RestOpenApiConsumerFactory {
 
     /**
      * Creates a new REST <a href="http://camel.apache.org/event-driven-consumer.html">Event Driven Consumer</a>, which
@@ -38,19 +39,12 @@ public interface RestConsumerFactory {
      *
      * @param  camelContext  the camel context
      * @param  processor     the processor
-     * @param  verb          HTTP verb such as GET, POST
-     * @param  basePath      base path
-     * @param  uriTemplate   uri template
-     * @param  consumes      media-types for what this REST service consume as input (accept-type), is <tt>null</tt> or
-     *                       <tt>&#42;/&#42;</tt> for anything
-     * @param  produces      media-types for what this REST service produces as output, can be <tt>null</tt>
      * @param  configuration REST configuration
      * @param  parameters    additional parameters
      * @return               a newly created REST consumer
      * @throws Exception     can be thrown
      */
     Consumer createConsumer(
-            CamelContext camelContext, Processor processor, String verb, String basePath, String uriTemplate,
-            String consumes, String produces, RestConfiguration configuration, Map<String, Object> parameters)
+            CamelContext camelContext, Processor processor, RestConfiguration configuration, Map<String, Object> parameters)
             throws Exception;
 }
diff --git a/core/camel-main/src/test/java/org/apache/camel/main/support/MockRestConsumerFactory.java b/core/camel-main/src/test/java/org/apache/camel/main/support/MockRestConsumerFactory.java
index e54fa2ea09a..6188601f62f 100644
--- a/core/camel-main/src/test/java/org/apache/camel/main/support/MockRestConsumerFactory.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/support/MockRestConsumerFactory.java
@@ -24,7 +24,11 @@ import org.apache.camel.Processor;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.RestConsumerFactory;
 
+/**
+ * Used for testing purpose in dsl
+ */
 public final class MockRestConsumerFactory implements RestConsumerFactory {
+
     @Override
     public Consumer createConsumer(
             CamelContext camelContext,
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
index 710861be507..3a2f0efae63 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
@@ -65,43 +65,6 @@ public interface RestOpenapiComponentBuilderFactory {
             doSetProperty("basePath", basePath);
             return this;
         }
-        /**
-         * Name of the Camel component that will perform the requests. The
-         * component must be present in Camel registry and it must implement
-         * RestProducerFactory service provider interface. If not set CLASSPATH
-         * is searched for single component that implements RestProducerFactory
-         * SPI. Can be overridden in endpoint configuration.
-         * 
-         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
-         * 
-         * Group: producer
-         * 
-         * @param componentName the value to set
-         * @return the dsl builder
-         */
-        default RestOpenapiComponentBuilder componentName(
-                java.lang.String componentName) {
-            doSetProperty("componentName", componentName);
-            return this;
-        }
-        /**
-         * What payload type this component capable of consuming. Could be one
-         * type, like application/json or multiple types as application/json,
-         * application/xml; q=0.5 according to the RFC7231. This equates to the
-         * value of Accept HTTP header. If set overrides any value found in the
-         * OpenApi specification. Can be overridden in endpoint configuration.
-         * 
-         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
-         * 
-         * Group: producer
-         * 
-         * @param consumes the value to set
-         * @return the dsl builder
-         */
-        default RestOpenapiComponentBuilder consumes(java.lang.String consumes) {
-            doSetProperty("consumes", consumes);
-            return this;
-        }
         /**
          * Scheme hostname and port to direct the HTTP requests to in the form
          * of https://hostname:port. Can be configured at the endpoint,
@@ -147,44 +110,6 @@ public interface RestOpenapiComponentBuilderFactory {
             doSetProperty("lazyStartProducer", lazyStartProducer);
             return this;
         }
-        /**
-         * What payload type this component is producing. For example
-         * application/json according to the RFC7231. This equates to the value
-         * of Content-Type HTTP header. If set overrides any value present in
-         * the OpenApi specification. Can be overridden in endpoint
-         * configuration.
-         * 
-         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
-         * 
-         * Group: producer
-         * 
-         * @param produces the value to set
-         * @return the dsl builder
-         */
-        default RestOpenapiComponentBuilder produces(java.lang.String produces) {
-            doSetProperty("produces", produces);
-            return this;
-        }
-        /**
-         * If request validation is enabled, this option provides the capability
-         * to customize the creation of OpenApiInteractionValidator used to
-         * validate requests.
-         * 
-         * The option is a:
-         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
-         * 
-         * Default:
-         * org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer
-         * Group: producer
-         * 
-         * @param requestValidationCustomizer the value to set
-         * @return the dsl builder
-         */
-        default RestOpenapiComponentBuilder requestValidationCustomizer(
-                org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer requestValidationCustomizer) {
-            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
-            return this;
-        }
         /**
          * Enable validation of requests against the configured OpenAPI
          * specification.
@@ -225,6 +150,61 @@ public interface RestOpenapiComponentBuilderFactory {
             doSetProperty("specificationUri", specificationUri);
             return this;
         }
+        /**
+         * Name of the Camel component that will perform the requests. The
+         * component must be present in Camel registry and it must implement
+         * RestProducerFactory service provider interface. If not set CLASSPATH
+         * is searched for single component that implements RestProducerFactory
+         * SPI. Can be overridden in endpoint configuration.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: producer (advanced)
+         * 
+         * @param componentName the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder componentName(
+                java.lang.String componentName) {
+            doSetProperty("componentName", componentName);
+            return this;
+        }
+        /**
+         * What payload type this component capable of consuming. Could be one
+         * type, like application/json or multiple types as application/json,
+         * application/xml; q=0.5 according to the RFC7231. This equates to the
+         * value of Accept HTTP header. If set overrides any value found in the
+         * OpenApi specification. Can be overridden in endpoint configuration.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: producer (advanced)
+         * 
+         * @param consumes the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder consumes(java.lang.String consumes) {
+            doSetProperty("consumes", consumes);
+            return this;
+        }
+        /**
+         * What payload type this component is producing. For example
+         * application/json according to the RFC7231. This equates to the value
+         * of Content-Type HTTP header. If set overrides any value present in
+         * the OpenApi specification. Can be overridden in endpoint
+         * configuration.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: producer (advanced)
+         * 
+         * @param produces the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder produces(java.lang.String produces) {
+            doSetProperty("produces", produces);
+            return this;
+        }
         /**
          * Whether autowiring is enabled. This is used for automatic autowiring
          * options (the option must be marked as autowired) by looking up in the
@@ -246,6 +226,24 @@ public interface RestOpenapiComponentBuilderFactory {
             doSetProperty("autowiredEnabled", autowiredEnabled);
             return this;
         }
+        /**
+         * If request validation is enabled, this option provides the capability
+         * to customize the creation of OpenApiInteractionValidator used to
+         * validate requests.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param requestValidationCustomizer the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder requestValidationCustomizer(
+                org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer requestValidationCustomizer) {
+            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
+            return this;
+        }
         /**
          * Customize TLS parameters used by the component. If not set defaults
          * to the TLS parameters set in the Camel context.
@@ -297,15 +295,15 @@ public interface RestOpenapiComponentBuilderFactory {
                 Object value) {
             switch (name) {
             case "basePath": ((RestOpenApiComponent) component).setBasePath((java.lang.String) value); return true;
-            case "componentName": ((RestOpenApiComponent) component).setComponentName((java.lang.String) value); return true;
-            case "consumes": ((RestOpenApiComponent) component).setConsumes((java.lang.String) value); return true;
             case "host": ((RestOpenApiComponent) component).setHost((java.lang.String) value); return true;
             case "lazyStartProducer": ((RestOpenApiComponent) component).setLazyStartProducer((boolean) value); return true;
-            case "produces": ((RestOpenApiComponent) component).setProduces((java.lang.String) value); return true;
-            case "requestValidationCustomizer": ((RestOpenApiComponent) component).setRequestValidationCustomizer((org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer) value); return true;
             case "requestValidationEnabled": ((RestOpenApiComponent) component).setRequestValidationEnabled((boolean) value); return true;
             case "specificationUri": ((RestOpenApiComponent) component).setSpecificationUri((java.net.URI) value); return true;
+            case "componentName": ((RestOpenApiComponent) component).setComponentName((java.lang.String) value); return true;
+            case "consumes": ((RestOpenApiComponent) component).setConsumes((java.lang.String) value); return true;
+            case "produces": ((RestOpenApiComponent) component).setProduces((java.lang.String) value); return true;
             case "autowiredEnabled": ((RestOpenApiComponent) component).setAutowiredEnabled((boolean) value); return true;
+            case "requestValidationCustomizer": ((RestOpenApiComponent) component).setRequestValidationCustomizer((org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer) value); return true;
             case "sslContextParameters": ((RestOpenApiComponent) component).setSslContextParameters((org.apache.camel.support.jsse.SSLContextParameters) value); return true;
             case "useGlobalSslContextParameters": ((RestOpenApiComponent) component).setUseGlobalSslContextParameters((boolean) value); return true;
             default: return false;
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
index 4a64b8a2b84..47d90bae33f 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
@@ -60,24 +60,6 @@ public interface RestOpenApiEndpointBuilderFactory {
             doSetProperty("basePath", basePath);
             return this;
         }
-        /**
-         * Name of the Camel component that will perform the requests. The
-         * component must be present in Camel registry and it must implement
-         * RestProducerFactory service provider interface. If not set CLASSPATH
-         * is searched for single component that implements RestProducerFactory
-         * SPI. Overrides component configuration.
-         * 
-         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
-         * 
-         * Group: producer
-         * 
-         * @param componentName the value to set
-         * @return the dsl builder
-         */
-        default RestOpenApiEndpointBuilder componentName(String componentName) {
-            doSetProperty("componentName", componentName);
-            return this;
-        }
         /**
          * What payload type this component capable of consuming. Could be one
          * type, like application/json or multiple types as application/json,
@@ -133,46 +115,6 @@ public interface RestOpenApiEndpointBuilderFactory {
             doSetProperty("produces", produces);
             return this;
         }
-        /**
-         * If request validation is enabled, this option provides the capability
-         * to customize the creation of OpenApiInteractionValidator used to
-         * validate requests.
-         * 
-         * The option is a:
-         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
-         * 
-         * Default:
-         * org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer
-         * Group: producer
-         * 
-         * @param requestValidationCustomizer the value to set
-         * @return the dsl builder
-         */
-        default RestOpenApiEndpointBuilder requestValidationCustomizer(
-                org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer requestValidationCustomizer) {
-            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
-            return this;
-        }
-        /**
-         * If request validation is enabled, this option provides the capability
-         * to customize the creation of OpenApiInteractionValidator used to
-         * validate requests.
-         * 
-         * The option will be converted to a
-         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
-         * 
-         * Default:
-         * org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer
-         * Group: producer
-         * 
-         * @param requestValidationCustomizer the value to set
-         * @return the dsl builder
-         */
-        default RestOpenApiEndpointBuilder requestValidationCustomizer(
-                String requestValidationCustomizer) {
-            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
-            return this;
-        }
         /**
          * Enable validation of requests against the configured OpenAPI
          * specification.
@@ -208,51 +150,6 @@ public interface RestOpenApiEndpointBuilderFactory {
             doSetProperty("requestValidationEnabled", requestValidationEnabled);
             return this;
         }
-        /**
-         * Levels for specific OpenAPI request validation options. Multiple
-         * options can be specified as URI options prefixed by 'validation.'.
-         * For example,
-         * validation.request.body=ERROR&amp;amp;validation.request.body.unexpected=IGNORED. Supported values are INFO, ERROR, WARN &amp;amp; IGNORE.
-         * 
-         * The option is a: &lt;code&gt;java.util.Map&amp;lt;java.lang.String,
-         * java.lang.Object&amp;gt;&lt;/code&gt; type.
-         * The option is multivalued, and you can use the
-         * requestValidationLevels(String, Object) method to add a value (call
-         * the method multiple times to set more values).
-         * 
-         * Group: producer
-         * 
-         * @param key the option key
-         * @param value the option value
-         * @return the dsl builder
-         */
-        default RestOpenApiEndpointBuilder requestValidationLevels(
-                String key,
-                Object value) {
-            doSetMultiValueProperty("requestValidationLevels", "validation." + key, value);
-            return this;
-        }
-        /**
-         * Levels for specific OpenAPI request validation options. Multiple
-         * options can be specified as URI options prefixed by 'validation.'.
-         * For example,
-         * validation.request.body=ERROR&amp;amp;validation.request.body.unexpected=IGNORED. Supported values are INFO, ERROR, WARN &amp;amp; IGNORE.
-         * 
-         * The option is a: &lt;code&gt;java.util.Map&amp;lt;java.lang.String,
-         * java.lang.Object&amp;gt;&lt;/code&gt; type.
-         * The option is multivalued, and you can use the
-         * requestValidationLevels(String, Object) method to add a value (call
-         * the method multiple times to set more values).
-         * 
-         * Group: producer
-         * 
-         * @param values the values
-         * @return the dsl builder
-         */
-        default RestOpenApiEndpointBuilder requestValidationLevels(Map values) {
-            doSetMultiValueProperties("requestValidationLevels", "validation.", values);
-            return this;
-        }
     }
 
     /**
@@ -264,6 +161,25 @@ public interface RestOpenApiEndpointBuilderFactory {
         default RestOpenApiEndpointBuilder basic() {
             return (RestOpenApiEndpointBuilder) this;
         }
+        /**
+         * Name of the Camel component that will perform the requests. The
+         * component must be present in Camel registry and it must implement
+         * RestProducerFactory service provider interface. If not set CLASSPATH
+         * is searched for single component that implements RestProducerFactory
+         * SPI. Overrides component configuration.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: producer (advanced)
+         * 
+         * @param componentName the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointBuilder componentName(
+                String componentName) {
+            doSetProperty("componentName", componentName);
+            return this;
+        }
         /**
          * Whether the producer should be started lazy (on the first message).
          * By starting lazy you can use this to allow CamelContext and routes to
@@ -313,6 +229,88 @@ public interface RestOpenApiEndpointBuilderFactory {
             doSetProperty("lazyStartProducer", lazyStartProducer);
             return this;
         }
+        /**
+         * If request validation is enabled, this option provides the capability
+         * to customize the creation of OpenApiInteractionValidator used to
+         * validate requests.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param requestValidationCustomizer the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointBuilder requestValidationCustomizer(
+                org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer requestValidationCustomizer) {
+            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
+            return this;
+        }
+        /**
+         * If request validation is enabled, this option provides the capability
+         * to customize the creation of OpenApiInteractionValidator used to
+         * validate requests.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param requestValidationCustomizer the value to set
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointBuilder requestValidationCustomizer(
+                String requestValidationCustomizer) {
+            doSetProperty("requestValidationCustomizer", requestValidationCustomizer);
+            return this;
+        }
+        /**
+         * Levels for specific OpenAPI request validation options. Multiple
+         * options can be specified as URI options prefixed by 'validation.'.
+         * For example,
+         * validation.request.body=ERROR&amp;amp;validation.request.body.unexpected=IGNORED. Supported values are INFO, ERROR, WARN &amp;amp; IGNORE.
+         * 
+         * The option is a: &lt;code&gt;java.util.Map&amp;lt;java.lang.String,
+         * java.lang.Object&amp;gt;&lt;/code&gt; type.
+         * The option is multivalued, and you can use the
+         * requestValidationLevels(String, Object) method to add a value (call
+         * the method multiple times to set more values).
+         * 
+         * Group: advanced
+         * 
+         * @param key the option key
+         * @param value the option value
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointBuilder requestValidationLevels(
+                String key,
+                Object value) {
+            doSetMultiValueProperty("requestValidationLevels", "validation." + key, value);
+            return this;
+        }
+        /**
+         * Levels for specific OpenAPI request validation options. Multiple
+         * options can be specified as URI options prefixed by 'validation.'.
+         * For example,
+         * validation.request.body=ERROR&amp;amp;validation.request.body.unexpected=IGNORED. Supported values are INFO, ERROR, WARN &amp;amp; IGNORE.
+         * 
+         * The option is a: &lt;code&gt;java.util.Map&amp;lt;java.lang.String,
+         * java.lang.Object&amp;gt;&lt;/code&gt; type.
+         * The option is multivalued, and you can use the
+         * requestValidationLevels(String, Object) method to add a value (call
+         * the method multiple times to set more values).
+         * 
+         * Group: advanced
+         * 
+         * @param values the values
+         * @return the dsl builder
+         */
+        default AdvancedRestOpenApiEndpointBuilder requestValidationLevels(
+                Map values) {
+            doSetMultiValueProperties("requestValidationLevels", "validation.", values);
+            return this;
+        }
     }
 
     public interface RestOpenApiBuilders {


(camel) 04/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit b40dc7c1a8006501cb064aadd25fc6571ec6d055
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Mar 24 12:59:35 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../openapi/RestOpenApiComponentConfigurer.java    |  12 ++
 .../openapi/RestOpenApiEndpointConfigurer.java     |  24 ++++
 .../openapi/RestOpenApiEndpointUriFactory.java     |   8 +-
 .../camel/component/rest/openapi/rest-openapi.json |  52 ++++----
 .../src/main/docs/rest-openapi-component.adoc      |   2 +-
 .../rest/openapi/RestOpenApiComponent.java         |  14 +++
 .../rest/openapi/RestOpenApiEndpoint.java          | 135 +++++++++++++++++++--
 .../apache/camel/spi/RestApiConsumerFactory.java   |   2 +-
 .../camel/spi/RestOpenApiConsumerFactory.java      |   4 +-
 9 files changed, 218 insertions(+), 35 deletions(-)

diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
index 8626436ff7f..ba22d771a42 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiComponentConfigurer.java
@@ -25,8 +25,12 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true;
         case "basepath":
         case "basePath": target.setBasePath(property(camelContext, java.lang.String.class, value)); return true;
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true;
         case "componentname":
         case "componentName": target.setComponentName(property(camelContext, java.lang.String.class, value)); return true;
+        case "consumercomponentname":
+        case "consumerComponentName": target.setConsumerComponentName(property(camelContext, java.lang.String.class, value)); return true;
         case "consumes": target.setConsumes(property(camelContext, java.lang.String.class, value)); return true;
         case "host": target.setHost(property(camelContext, java.lang.String.class, value)); return true;
         case "lazystartproducer":
@@ -53,8 +57,12 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "autowiredEnabled": return boolean.class;
         case "basepath":
         case "basePath": return java.lang.String.class;
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": return boolean.class;
         case "componentname":
         case "componentName": return java.lang.String.class;
+        case "consumercomponentname":
+        case "consumerComponentName": return java.lang.String.class;
         case "consumes": return java.lang.String.class;
         case "host": return java.lang.String.class;
         case "lazystartproducer":
@@ -82,8 +90,12 @@ public class RestOpenApiComponentConfigurer extends PropertyConfigurerSupport im
         case "autowiredEnabled": return target.isAutowiredEnabled();
         case "basepath":
         case "basePath": return target.getBasePath();
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": return target.isBridgeErrorHandler();
         case "componentname":
         case "componentName": return target.getComponentName();
+        case "consumercomponentname":
+        case "consumerComponentName": return target.getConsumerComponentName();
         case "consumes": return target.getConsumes();
         case "host": return target.getHost();
         case "lazystartproducer":
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
index 664a2cb990a..3c8adaec8e9 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointConfigurer.java
@@ -23,9 +23,17 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "basepath":
         case "basePath": target.setBasePath(property(camelContext, java.lang.String.class, value)); return true;
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true;
         case "componentname":
         case "componentName": target.setComponentName(property(camelContext, java.lang.String.class, value)); return true;
+        case "consumercomponentname":
+        case "consumerComponentName": target.setConsumerComponentName(property(camelContext, java.lang.String.class, value)); return true;
         case "consumes": target.setConsumes(property(camelContext, java.lang.String.class, value)); return true;
+        case "exceptionhandler":
+        case "exceptionHandler": target.setExceptionHandler(property(camelContext, org.apache.camel.spi.ExceptionHandler.class, value)); return true;
+        case "exchangepattern":
+        case "exchangePattern": target.setExchangePattern(property(camelContext, org.apache.camel.ExchangePattern.class, value)); return true;
         case "host": target.setHost(property(camelContext, java.lang.String.class, value)); return true;
         case "lazystartproducer":
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
@@ -45,9 +53,17 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "basepath":
         case "basePath": return java.lang.String.class;
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": return boolean.class;
         case "componentname":
         case "componentName": return java.lang.String.class;
+        case "consumercomponentname":
+        case "consumerComponentName": return java.lang.String.class;
         case "consumes": return java.lang.String.class;
+        case "exceptionhandler":
+        case "exceptionHandler": return org.apache.camel.spi.ExceptionHandler.class;
+        case "exchangepattern":
+        case "exchangePattern": return org.apache.camel.ExchangePattern.class;
         case "host": return java.lang.String.class;
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
@@ -68,9 +84,17 @@ public class RestOpenApiEndpointConfigurer extends PropertyConfigurerSupport imp
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "basepath":
         case "basePath": return target.getBasePath();
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": return target.isBridgeErrorHandler();
         case "componentname":
         case "componentName": return target.getComponentName();
+        case "consumercomponentname":
+        case "consumerComponentName": return target.getConsumerComponentName();
         case "consumes": return target.getConsumes();
+        case "exceptionhandler":
+        case "exceptionHandler": return target.getExceptionHandler();
+        case "exchangepattern":
+        case "exchangePattern": return target.getExchangePattern();
         case "host": return target.getHost();
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
diff --git a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
index 43d1ec6ff59..8cf0fd1124f 100644
--- a/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
+++ b/components/camel-rest-openapi/src/generated/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointUriFactory.java
@@ -21,10 +21,14 @@ public class RestOpenApiEndpointUriFactory extends org.apache.camel.support.comp
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(11);
+        Set<String> props = new HashSet<>(15);
         props.add("basePath");
+        props.add("bridgeErrorHandler");
         props.add("componentName");
+        props.add("consumerComponentName");
         props.add("consumes");
+        props.add("exceptionHandler");
+        props.add("exchangePattern");
         props.add("host");
         props.add("lazyStartProducer");
         props.add("operationId");
@@ -53,7 +57,7 @@ public class RestOpenApiEndpointUriFactory extends org.apache.camel.support.comp
         Map<String, Object> copy = new HashMap<>(properties);
 
         uri = buildPathParameter(syntax, uri, "specificationUri", "openapi.json", false, copy);
-        uri = buildPathParameter(syntax, uri, "operationId", null, true, copy);
+        uri = buildPathParameter(syntax, uri, "operationId", null, false, copy);
         uri = buildQueryParameters(uri, copy, encode);
         return uri;
     }
diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index 9242b3b9735..b817e5a6551 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -18,35 +18,41 @@
     "async": false,
     "api": false,
     "consumerOnly": false,
-    "producerOnly": true,
+    "producerOnly": false,
     "lenientProperties": false,
     "remote": true
   },
   "componentProperties": {
-    "basePath": { "index": 0, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
-    "host": { "index": 1, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
-    "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "requestValidationEnabled": { "index": 3, "kind": "property", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "specificationUri": { "index": 4, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
-    "componentName": { "index": 5, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
-    "consumes": { "index": 6, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
-    "produces": { "index": 7, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi sp [...]
-    "autowiredEnabled": { "index": 8, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
-    "requestValidationCustomizer": { "index": 9, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator us [...]
-    "sslContextParameters": { "index": 10, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
-    "useGlobalSslContextParameters": { "index": 11, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
+    "requestValidationEnabled": { "index": 0, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
+    "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
+    "consumerComponentName": { "index": 2, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
+    "basePath": { "index": 3, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
+    "host": { "index": 4, "kind": "property", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a nam [...]
+    "lazyStartProducer": { "index": 5, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "specificationUri": { "index": 6, "kind": "property", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If  [...]
+    "componentName": { "index": 7, "kind": "property", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH  [...]
+    "consumes": { "index": 8, "kind": "property", "displayName": "Consumes", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the val [...]
+    "produces": { "index": 9, "kind": "property", "displayName": "Produces", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi sp [...]
+    "autowiredEnabled": { "index": 10, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching  [...]
+    "requestValidationCustomizer": { "index": 11, "kind": "property", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
+    "sslContextParameters": { "index": 12, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" },
+    "useGlobalSslContextParameters": { "index": 13, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." }
   },
   "properties": {
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not  [...]
-    "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification." },
-    "basePath": { "index": 2, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
-    "consumes": { "index": 3, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
-    "host": { "index": 4, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
-    "produces": { "index": 5, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overri [...]
-    "requestValidationEnabled": { "index": 6, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "componentName": { "index": 7, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPATH [...]
-    "lazyStartProducer": { "index": 8, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...]
-    "requestValidationCustomizer": { "index": 9, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator u [...]
-    "requestValidationLevels": { "index": 10, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
+    "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
+    "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
+    "bridgeErrorHandler": { "index": 3, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
+    "consumerComponentName": { "index": 4, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
+    "exceptionHandler": { "index": 5, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
+    "exchangePattern": { "index": 6, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
+    "basePath": { "index": 7, "kind": "parameter", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v3. Default is unset, if set overrides the value present in OpenApi specification and in the component configuration." },
+    "consumes": { "index": 8, "kind": "parameter", "displayName": "Consumes", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
+    "host": { "index": 9, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Scheme hostname and port to direct the HTTP requests to in the form of https:\/\/hostname:port. Can be configured at the endpoint, component or in the corresponding REST configuration in the Camel Context. If you give this component a na [...]
+    "produces": { "index": 10, "kind": "parameter", "displayName": "Produces", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component is producing. For example application\/json according to the RFC7231. This equates to the value of Content-Type HTTP header. If set overrides any value present in the OpenApi specification. Overr [...]
+    "componentName": { "index": 11, "kind": "parameter", "displayName": "Component Name", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will perform the requests. The component must be present in Camel registry and it must implement RestProducerFactory service provider interface. If not set CLASSPAT [...]
+    "lazyStartProducer": { "index": 12, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+    "requestValidationCustomizer": { "index": 13, "kind": "parameter", "displayName": "Request Validation Customizer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer", "deprecated": false, "autowired": false, "secret": false, "description": "If request validation is enabled, this option provides the capability to customize the creation of OpenApiInteractionValidator  [...]
+    "requestValidationLevels": { "index": 14, "kind": "parameter", "displayName": "Request Validation Levels", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "validation.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Levels for specific OpenAPI request validation options. Multiple options can be specified as URI options prefixed by ' [...]
   }
 }
diff --git a/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc b/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc
index c580baafcd4..e521f8767d0 100644
--- a/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc
+++ b/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc
@@ -6,7 +6,7 @@
 :since: 3.1
 :supportlevel: Stable
 :tabs-sync-option:
-:component-header: Only producer is supported
+:component-header: Both producer and consumer are supported
 //Manually maintained attributes
 :camel-spring-boot-name: rest-openapi
 
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index ec4acc1707d..497431226a8 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -94,6 +94,12 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
                             + " endpoint configuration.",
               label = "producer,advanced")
     private String componentName;
+    @Metadata(description = "Name of the Camel component that will service the requests. The component must be present"
+                            + " in Camel registry and it must implement RestOpenApiConsumerFactory service provider interface. If not set"
+                            + " CLASSPATH is searched for single component that implements RestOpenApiConsumerFactory SPI.  Can be overridden in"
+                            + " endpoint configuration.",
+              label = "consumer,advanced")
+    private String consumerComponentName;
     @Metadata(description = "Scheme hostname and port to direct the HTTP requests to in the form of"
                             + " `http[s]://hostname[:port]`. Can be configured at the endpoint, component or in the corresponding"
                             + " REST configuration in the Camel Context. If you give this component a name (e.g. `petstore`) that"
@@ -158,6 +164,10 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         return componentName;
     }
 
+    public String getConsumerComponentName() {
+        return consumerComponentName;
+    }
+
     public String getConsumes() {
         return consumes;
     }
@@ -191,6 +201,10 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         this.componentName = notEmpty(componentName, "componentName");
     }
 
+    public void setConsumerComponentName(String consumerComponentName) {
+        this.consumerComponentName = consumerComponentName;
+    }
+
     public void setConsumes(final String consumes) {
         this.consumes = isMediaRange(consumes, "consumes");
     }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index bb80f463521..1fd6f314adc 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -54,18 +54,20 @@ import io.swagger.v3.parser.core.models.ParseOptions;
 import io.swagger.v3.parser.core.models.SwaggerParseResult;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Category;
+import org.apache.camel.Component;
 import org.apache.camel.Consumer;
 import org.apache.camel.Endpoint;
 import org.apache.camel.ExchangePattern;
+import org.apache.camel.NoSuchBeanException;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
 import org.apache.camel.component.rest.openapi.validator.DefaultRequestValidationCustomizer;
 import org.apache.camel.component.rest.openapi.validator.RequestValidationCustomizer;
 import org.apache.camel.component.rest.openapi.validator.RequestValidator;
 import org.apache.camel.component.rest.openapi.validator.RestOpenApiOperation;
-import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.Resource;
 import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.spi.RestOpenApiConsumerFactory;
 import org.apache.camel.spi.UriEndpoint;
 import org.apache.camel.spi.UriParam;
 import org.apache.camel.spi.UriPath;
@@ -77,6 +79,7 @@ import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.StringHelper;
 import org.apache.camel.util.UnsafeUriCharactersEncoder;
 import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static java.util.Optional.ofNullable;
@@ -92,10 +95,14 @@ import static org.apache.camel.util.StringHelper.notEmpty;
  * To call REST services using OpenAPI specification as contract.
  */
 @UriEndpoint(firstVersion = "3.1.0", scheme = "rest-openapi", title = "REST OpenApi",
-             syntax = "rest-openapi:specificationUri#operationId", category = { Category.REST, Category.API },
-             producerOnly = true)
+             syntax = "rest-openapi:specificationUri#operationId", category = { Category.REST, Category.API })
 public final class RestOpenApiEndpoint extends DefaultEndpoint {
 
+    private static final Logger LOG = LoggerFactory.getLogger(RestOpenApiEndpoint.class);
+
+    public static final String[] DEFAULT_REST_OPENAPI_CONSUMER_COMPONENTS
+            = new String[] { "platform-http" };
+
     /**
      * Remaining parameters specified in the Endpoint URI.
      */
@@ -111,6 +118,12 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
                             + " component configuration.",
               label = "producer,advanced")
     private String componentName;
+    @UriParam(description = "Name of the Camel component that will service the requests. The component must be present"
+                            + " in Camel registry and it must implement RestOpenApiConsumerFactory service provider interface. If not set"
+                            + " CLASSPATH is searched for single component that implements RestOpenApiConsumerFactory SPI. Overrides"
+                            + " component configuration.",
+              label = "consumer,advanced")
+    private String consumerComponentName;
     @UriParam(description = "Scheme hostname and port to direct the HTTP requests to in the form of"
                             + " `http[s]://hostname[:port]`. Can be configured at the endpoint, component or in the corresponding"
                             + " REST configuration in the Camel Context. If you give this component a name (e.g. `petstore`) that"
@@ -119,8 +132,8 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
                             + " configuration.",
               label = "producer")
     private String host;
-    @UriPath(description = "ID of the operation from the OpenApi specification.", label = "producer")
-    @Metadata(required = true)
+    @UriPath(description = "ID of the operation from the OpenApi specification. This is required when using producer",
+             label = "producer")
     private String operationId;
     @UriParam(description = "What payload type this component capable of consuming. Could be one type, like `application/json`"
                             + " or multiple types as `application/json, application/xml; q=0.5` according to the RFC7231. This equates"
@@ -182,7 +195,103 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
 
     @Override
     public Consumer createConsumer(final Processor processor) throws Exception {
-        throw new UnsupportedOperationException("Consumer not supported");
+        final CamelContext camelContext = getCamelContext();
+        final OpenAPI openapiDoc = loadSpecificationFrom(camelContext, specificationUri);
+        String path = determineBasePath(openapiDoc);
+
+        // TODO: processor should use OpenAPI to detect which operations exists, and map to direct:xx
+        // TODO: validate on|poff
+
+        return createConsumerFor(path, processor);
+    }
+
+    protected Consumer createConsumerFor(String basePath, Processor processor) throws Exception {
+        RestOpenApiConsumerFactory factory = null;
+        String cname = null;
+        if (getConsumerComponentName() != null) {
+            Object comp = getCamelContext().getRegistry().lookupByName(getConsumerComponentName());
+            if (comp instanceof RestOpenApiConsumerFactory) {
+                factory = (RestOpenApiConsumerFactory) comp;
+            } else {
+                comp = getCamelContext().getComponent(getConsumerComponentName());
+                if (comp instanceof RestOpenApiConsumerFactory) {
+                    factory = (RestOpenApiConsumerFactory) comp;
+                }
+            }
+
+            if (factory == null) {
+                if (comp != null) {
+                    throw new IllegalArgumentException(
+                            "Component " + getConsumerComponentName() + " is not a RestOpenApiConsumerFactory");
+                } else {
+                    throw new NoSuchBeanException(getConsumerComponentName(), RestOpenApiConsumerFactory.class.getName());
+                }
+            }
+            cname = getConsumerComponentName();
+        }
+
+        // try all components
+        if (factory == null) {
+            for (String name : getCamelContext().getComponentNames()) {
+                Component comp = getCamelContext().getComponent(name);
+                if (comp instanceof RestOpenApiConsumerFactory) {
+                    factory = (RestOpenApiConsumerFactory) comp;
+                    cname = name;
+                    break;
+                }
+            }
+        }
+
+        // favour using platform-http if available on classpath
+        if (factory == null) {
+            Object comp = getCamelContext().getComponent("platform-http", true);
+            if (comp instanceof RestOpenApiConsumerFactory) {
+                factory = (RestOpenApiConsumerFactory) comp;
+                LOG.debug("Auto discovered platform-http as RestConsumerFactory");
+            }
+        }
+
+        // lookup in registry
+        if (factory == null) {
+            Set<RestOpenApiConsumerFactory> factories
+                    = getCamelContext().getRegistry().findByType(RestOpenApiConsumerFactory.class);
+            if (factories != null && factories.size() == 1) {
+                factory = factories.iterator().next();
+            }
+        }
+
+        // no explicit factory found then try to see if we can find any of the default rest consumer components
+        // and there must only be exactly one so we safely can pick this one
+        if (factory == null) {
+            RestOpenApiConsumerFactory found = null;
+            String foundName = null;
+            for (String name : DEFAULT_REST_OPENAPI_CONSUMER_COMPONENTS) {
+                Object comp = getCamelContext().getComponent(name, true);
+                if (comp instanceof RestOpenApiConsumerFactory) {
+                    if (found == null) {
+                        found = (RestOpenApiConsumerFactory) comp;
+                        foundName = name;
+                    } else {
+                        throw new IllegalArgumentException(
+                                "Multiple RestOpenApiConsumerFactory found on classpath. Configure explicit which component to use");
+                    }
+                }
+            }
+            if (found != null) {
+                LOG.debug("Auto discovered {} as RestOpenApiConsumerFactory", foundName);
+                factory = found;
+            }
+        }
+
+        if (factory != null) {
+            RestConfiguration config = CamelContextHelper.getRestConfiguration(getCamelContext(), cname);
+            Map<String, Object> copy = new HashMap<>(parameters); // defensive copy of the parameters
+            Consumer consumer = factory.createConsumer(getCamelContext(), processor, basePath, config, copy);
+            configureConsumer(consumer);
+            return consumer;
+        } else {
+            throw new IllegalStateException("Cannot find RestOpenApiConsumerFactory in Registry or as a Component to use");
+        }
     }
 
     @Override
@@ -237,6 +346,10 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         return componentName;
     }
 
+    public String getConsumerComponentName() {
+        return consumerComponentName;
+    }
+
     public String getConsumes() {
         return consumes;
     }
@@ -267,7 +380,11 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     }
 
     public void setComponentName(final String componentName) {
-        this.componentName = notEmpty(componentName, "componentName");
+        this.componentName = componentName;
+    }
+
+    public void setConsumerComponentName(String consumerComponentName) {
+        this.consumerComponentName = consumerComponentName;
     }
 
     public void setConsumes(final String consumes) {
@@ -418,6 +535,10 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
         return Optional.ofNullable(componentName).orElse(getComponent().getComponentName());
     }
 
+    String determineConsumerComponentName() {
+        return Optional.ofNullable(consumerComponentName).orElse(getComponent().getConsumerComponentName());
+    }
+
     Map<String, Object> determineEndpointParameters(final OpenAPI openapi, final Operation operation) {
         final Map<String, Object> parameters = new HashMap<>();
 
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RestApiConsumerFactory.java b/core/camel-api/src/main/java/org/apache/camel/spi/RestApiConsumerFactory.java
index e2a6dcc5b96..82e5b9e735e 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RestApiConsumerFactory.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RestApiConsumerFactory.java
@@ -38,8 +38,8 @@ public interface RestApiConsumerFactory {
      * @param  camelContext the camel context
      * @param  processor    the processor
      * @param  contextPath  the context-path
+     * @param  configuration REST configuration
      * @param  parameters   additional parameters
-     *
      * @return              a newly created REST API consumer
      * @throws Exception    can be thrown
      */
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java b/core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java
index 5022a1b8bf2..99a2ff513fa 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RestOpenApiConsumerFactory.java
@@ -39,12 +39,14 @@ public interface RestOpenApiConsumerFactory {
      *
      * @param  camelContext  the camel context
      * @param  processor     the processor
+     * @param  contextPath  the context-path
      * @param  configuration REST configuration
      * @param  parameters    additional parameters
      * @return               a newly created REST consumer
      * @throws Exception     can be thrown
      */
     Consumer createConsumer(
-            CamelContext camelContext, Processor processor, RestConfiguration configuration, Map<String, Object> parameters)
+            CamelContext camelContext, Processor processor, String contextPath,
+            RestConfiguration configuration, Map<String, Object> parameters)
             throws Exception;
 }


(camel) 18/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 9f64e573b6eeb442c0662079288ff8ac5f67c26e
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 13:48:54 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../camel/catalog/components/rest-openapi.json     |  4 +--
 .../vertx/PlatformHttpRestOpenApiConsumerTest.java | 38 ++++++++++++++++++++++
 .../camel/component/rest/openapi/rest-openapi.json |  4 +--
 .../DefaultRestOpenapiProcessorStrategy.java       | 19 +++++++++--
 .../rest/openapi/RestOpenApiComponent.java         |  4 +--
 .../rest/openapi/RestOpenApiEndpoint.java          |  4 +--
 .../dsl/RestOpenapiComponentBuilderFactory.java    | 18 ++++++++++
 .../dsl/RestOpenApiEndpointBuilderFactory.java     |  4 +--
 .../camel/kotlin/components/RestOpenapiUriDsl.kt   |  2 +-
 9 files changed, 83 insertions(+), 14 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index fae90af3743..d6b3784e2d9 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -25,7 +25,7 @@
   "componentProperties": {
     "requestValidationEnabled": { "index": 0, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
-    "missingOperation": { "index": 2, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "dummy" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route." },
+    "missingOperation": { "index": 2, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
     "consumerComponentName": { "index": 3, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
     "restOpenapiProcessorStrategy": { "index": 4, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
     "basePath": { "index": 5, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
@@ -44,7 +44,7 @@
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not give [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
     "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "missingOperation": { "index": 3, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "dummy" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route." },
+    "missingOperation": { "index": 3, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
     "bridgeErrorHandler": { "index": 4, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
     "consumerComponentName": { "index": 5, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
     "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
index c41839ef21f..57acb01609d 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
@@ -51,6 +51,7 @@ public class PlatformHttpRestOpenApiConsumerTest {
                     .then()
                     .statusCode(200)
                     .body(equalTo("{\"pet\": \"tony the tiger\"}"));
+
         } finally {
             context.stop();
         }
@@ -87,6 +88,43 @@ public class PlatformHttpRestOpenApiConsumerTest {
         }
     }
 
+    @Test
+    public void testRestOpenApiMock() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("rest-openapi:classpath:openapi-v3.json?missingOperation=mock")
+                            .log("dummy");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .get("/api/v3/pet/123")
+                    .then()
+                    .statusCode(200)
+                    .body(equalTo("{\"pet\": \"tony the tiger\"}"));
+
+            // mocked gives empty response
+            given()
+                    .when()
+                    .get("/api/v3/pet/findByTags")
+                    .then()
+                    .statusCode(204)
+                    .body(equalTo(""));
+        } finally {
+            context.stop();
+        }
+    }
+
     @Test
     public void testRestOpenApiMissingOperation() throws Exception {
         final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index fae90af3743..d6b3784e2d9 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -25,7 +25,7 @@
   "componentProperties": {
     "requestValidationEnabled": { "index": 0, "kind": "property", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
     "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the like [...]
-    "missingOperation": { "index": 2, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "dummy" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route." },
+    "missingOperation": { "index": 2, "kind": "property", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
     "consumerComponentName": { "index": 3, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfac [...]
     "restOpenapiProcessorStrategy": { "index": 4, "kind": "property", "displayName": "Rest Openapi Processor Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom strategy for how to process Rest DSL requests" },
     "basePath": { "index": 5, "kind": "property", "displayName": "Base Path", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "API basePath, for example \/v2. Default is unset, if set overrides the value present in OpenApi specification." },
@@ -44,7 +44,7 @@
     "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.net.URI", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not give [...]
     "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
     "requestValidationEnabled": { "index": 2, "kind": "parameter", "displayName": "Request Validation Enabled", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable validation of requests against the configured OpenAPI specification" },
-    "missingOperation": { "index": 3, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "dummy" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route." },
+    "missingOperation": { "index": 3, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
     "bridgeErrorHandler": { "index": 4, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming  [...]
     "consumerComponentName": { "index": 5, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
     "exceptionHandler": { "index": 6, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By def [...]
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index f150912331e..40709fb260a 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -82,14 +82,27 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
                 throw new IllegalArgumentException(msg);
             } else if ("ignore".equalsIgnoreCase(missingOperation)) {
                 LOG.warn(msg + ". This validation error is ignored.");
-            } else if ("dev".equalsIgnoreCase(missingOperation)) {
-                LOG.warn(msg + ". This validation error is ignored when running in developer mode (profile=dev).");
+            } else if ("mock".equalsIgnoreCase(missingOperation)) {
+                LOG.debug(msg + ". This validation error is ignored (Will return a mocked/empty response).");
             }
         }
     }
 
     @Override
     public boolean process(Operation operation, String path, Exchange exchange, AsyncCallback callback) {
+        if ("mock".equalsIgnoreCase(missingOperation)) {
+            // check if there is a route
+            Endpoint e = camelContext.hasEndpoint(component + ":" + operation.getOperationId());
+            if (e == null) {
+                // no route for the given operation, so lets return an empty response
+                exchange.getMessage().setBody("");
+                // TODO: load canned response from classpath if exist
+                exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 204);
+                callback.done(true);
+                return true;
+            }
+        }
+
         Endpoint e = camelContext.getEndpoint(component + ":" + operation.getOperationId());
         AsyncProducer p = producerCache.acquireProducer(e);
         return p.process(exchange, doneSync -> {
@@ -138,7 +151,7 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
         // automatic adjust missing operation to fail, and ignore if you use developer mode
         if (missingOperation == null) {
             boolean dev = "dev".equalsIgnoreCase(camelContext.getCamelContextExtension().getProfile());
-            missingOperation = dev ? "dev" : "fail";
+            missingOperation = dev ? "mock" : "fail";
         }
     }
 
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index e248acbc4aa..07dfb4556f1 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -141,8 +141,8 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
     private SSLContextParameters sslContextParameters;
     @Metadata(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
     private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
-    @Metadata(description = "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route.",
-              enums = "fail,ignore,dummy", label = "consumer", defaultValue = "fail")
+    @Metadata(description = "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.",
+              enums = "fail,ignore,mock", label = "consumer", defaultValue = "fail")
     private String missingOperation;
 
     public RestOpenApiComponent() {
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 9dbcd3df054..df8eeafa072 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -166,8 +166,8 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     private Map<String, Object> requestValidationLevels = new HashMap<>();
     @UriParam(description = "To use a custom strategy for how to process Rest DSL requests", label = "consumer,advanced")
     private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy;
-    @UriParam(description = "Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that are not mapped to a corresponding route.",
-              enums = "fail,ignore,dummy", label = "consumer", defaultValue = "fail")
+    @UriParam(description = "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route.",
+              enums = "fail,ignore,mock", label = "consumer", defaultValue = "fail")
     private String missingOperation;
 
     public RestOpenApiEndpoint() {
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
index 077b716fab2..064b5f66d51 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/RestOpenapiComponentBuilderFactory.java
@@ -94,6 +94,23 @@ public interface RestOpenapiComponentBuilderFactory {
             doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
             return this;
         }
+        /**
+         * Whether the consumer should fail,ignore or return a mock response for
+         * OpenAPI operations that are not mapped to a corresponding route.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Default: fail
+         * Group: consumer
+         * 
+         * @param missingOperation the value to set
+         * @return the dsl builder
+         */
+        default RestOpenapiComponentBuilder missingOperation(
+                java.lang.String missingOperation) {
+            doSetProperty("missingOperation", missingOperation);
+            return this;
+        }
         /**
          * Name of the Camel component that will service the requests. The
          * component must be present in Camel registry and it must implement
@@ -359,6 +376,7 @@ public interface RestOpenapiComponentBuilderFactory {
             switch (name) {
             case "requestValidationEnabled": ((RestOpenApiComponent) component).setRequestValidationEnabled((boolean) value); return true;
             case "bridgeErrorHandler": ((RestOpenApiComponent) component).setBridgeErrorHandler((boolean) value); return true;
+            case "missingOperation": ((RestOpenApiComponent) component).setMissingOperation((java.lang.String) value); return true;
             case "consumerComponentName": ((RestOpenApiComponent) component).setConsumerComponentName((java.lang.String) value); return true;
             case "restOpenapiProcessorStrategy": ((RestOpenApiComponent) component).setRestOpenapiProcessorStrategy((org.apache.camel.component.rest.openapi.RestOpenapiProcessorStrategy) value); return true;
             case "basePath": ((RestOpenApiComponent) component).setBasePath((java.lang.String) value); return true;
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
index d3545200a49..78546192e62 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
@@ -80,8 +80,8 @@ public interface RestOpenApiEndpointBuilderFactory {
             return this;
         }
         /**
-         * Whether the consumer should fail,ignore or return a dummy response
-         * for OpenAPI operations that are not mapped to a corresponding route.
+         * Whether the consumer should fail,ignore or return a mock response for
+         * OpenAPI operations that are not mapped to a corresponding route.
          * 
          * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
          * 
diff --git a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
index 915720a83d6..a4e550f2223 100644
--- a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
+++ b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
@@ -84,7 +84,7 @@ public class RestOpenapiUriDsl(
   }
 
   /**
-   * Whether the consumer should fail,ignore or return a dummy response for OpenAPI operations that
+   * Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that
    * are not mapped to a corresponding route.
    */
   public fun missingOperation(missingOperation: String) {


(camel) 15/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit c104cc1762c3ba0446bc562660082c6fa88e276b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 10:59:32 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../vertx/PlatformHttpRestOpenApiConsumerTest.java | 28 +++++++++++
 .../rest/openapi/RestOpenApiComponent.java         |  6 +--
 .../rest/openapi/RestOpenApiEndpoint.java          |  2 +-
 .../rest/openapi/RestOpenApiProcessor.java         | 55 +++++++++++++++++-----
 .../validator/RequestValidationCustomizer.java     |  1 +
 .../rest/openapi/validator/RequestValidator.java   | 31 ++++++------
 6 files changed, 90 insertions(+), 33 deletions(-)

diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
index 6c9865ecb59..1ea0a976913 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
@@ -110,4 +110,32 @@ public class PlatformHttpRestOpenApiConsumerTest {
         }
     }
 
+    @Test
+    public void testRestOpenApiValidate() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("rest-openapi:classpath:openapi-v3.json?requestValidationEnabled=true")
+                            .log("dummy");
+
+                    from("direct:updatePet")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .put("/api/v3/pet")
+                    .then()
+                    .statusCode(405); // no request body
+        } finally {
+            context.stop();
+        }
+    }
+
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index b405b1466c5..98ea9e91fe4 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -128,8 +128,7 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
                             + " configuration.",
               defaultValue = DEFAULT_SPECIFICATION_URI_STR, label = "producer")
     private URI specificationUri;
-    @Metadata(description = "Enable validation of requests against the configured OpenAPI specification",
-              defaultValue = "false")
+    @Metadata(description = "Enable validation of requests against the configured OpenAPI specification")
     private boolean requestValidationEnabled;
     @Metadata(description = "If request validation is enabled, this option provides the capability to customize"
                             + " the creation of OpenApiInteractionValidator used to validate requests.",
@@ -252,8 +251,7 @@ public final class RestOpenApiComponent extends DefaultComponent implements SSLC
         return this.requestValidationEnabled;
     }
 
-    public void setRequestValidationCustomizer(
-            RequestValidationCustomizer requestValidationCustomizer) {
+    public void setRequestValidationCustomizer(RequestValidationCustomizer requestValidationCustomizer) {
         this.requestValidationCustomizer = requestValidationCustomizer;
     }
 
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 034a7e3e56b..2c55358dacf 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -206,7 +206,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
     public Consumer createConsumer(final Processor processor) throws Exception {
         OpenAPI doc = loadSpecificationFrom(getCamelContext(), specificationUri);
         String path = determineBasePath(doc);
-        Processor target = new RestOpenApiProcessor(doc, path, processor);
+        Processor target = new RestOpenApiProcessor(this, doc, path, processor);
         CamelContextAware.trySetCamelContext(target, getCamelContext());
         return createConsumerFor(path, target);
     }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index 5e3291d82c9..b1000f26ccc 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -18,10 +18,16 @@ package org.apache.camel.component.rest.openapi;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.parameters.Parameter;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
@@ -38,14 +44,15 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
             = Arrays.asList("GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "OPTIONS", "CONNECT", "PATCH");
 
     private CamelContext camelContext;
+    private final RestOpenApiEndpoint endpoint;
     private final OpenAPI openAPI;
     private final String basePath;
     private final List<RestConsumerContextPathMatcher.ConsumerPath<Operation>> paths = new ArrayList<>();
     private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy;
-    private RequestValidator requestValidator;
 
-    public RestOpenApiProcessor(OpenAPI openAPI, String basePath, Processor processor) {
+    public RestOpenApiProcessor(RestOpenApiEndpoint endpoint, OpenAPI openAPI, String basePath, Processor processor) {
         super(processor);
+        this.endpoint = endpoint;
         this.basePath = basePath;
         this.openAPI = openAPI;
         this.restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy();
@@ -69,17 +76,8 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
         this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy;
     }
 
-    public RequestValidator getRequestValidator() {
-        return requestValidator;
-    }
-
-    public void setRequestValidator(RequestValidator requestValidator) {
-        this.requestValidator = requestValidator;
-    }
-
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
-        // TODO: RequestValidator
         // TODO: binding
 
         String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);
@@ -91,8 +89,39 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
         RestConsumerContextPathMatcher.ConsumerPath<Operation> m
                 = RestConsumerContextPathMatcher.matchBestPath(verb, path, paths);
         if (m != null) {
-            Operation o = m.getConsumer();
-            return restOpenapiProcessorStrategy.process(o, path, exchange, callback);
+            Operation operation = m.getConsumer();
+
+            // we have found the operation to call, but if validation is enabled then we need
+            // to validate the incoming request first
+            if (endpoint.isRequestValidationEnabled()) {
+                Map<String, Parameter> pathParameters;
+                if (operation.getParameters() != null) {
+                    pathParameters = operation.getParameters().stream()
+                            .filter(p -> "path".equals(p.getIn()))
+                            .collect(Collectors.toMap(Parameter::getName, Function.identity()));
+                } else {
+                    pathParameters = new HashMap<>();
+                }
+                try {
+                    final String uriTemplate = endpoint.resolveUri(path, pathParameters);
+                    RequestValidator validator = endpoint.configureRequestValidator(openAPI, operation, verb, uriTemplate);
+                    Set<String> errors = validator.validate(exchange);
+                    if (!errors.isEmpty()) {
+                        RestOpenApiValidationException exception = new RestOpenApiValidationException(errors);
+                        exchange.setException(exception);
+                        // validation error should be 405
+                        exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 405);
+                        callback.done(true);
+                        return true;
+                    }
+                } catch (Exception e) {
+                    exchange.setException(e);
+                    callback.done(true);
+                    return true;
+                }
+            }
+
+            return restOpenapiProcessorStrategy.process(operation, path, exchange, callback);
         }
 
         // okay we cannot process this requires so return either 404 or 405.
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/validator/RequestValidationCustomizer.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/validator/RequestValidationCustomizer.java
index 5ac2c99d286..42a5913bab6 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/validator/RequestValidationCustomizer.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/validator/RequestValidationCustomizer.java
@@ -24,6 +24,7 @@ import org.apache.camel.Exchange;
  * An abstraction for customizing the behavior of OpenApi request validation.
  */
 public interface RequestValidationCustomizer {
+
     /**
      * Customizes the creation of a {@link OpenApiInteractionValidator}. The default implementation enables validation
      * of only the request body.
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/validator/RequestValidator.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/validator/RequestValidator.java
index 7636f668527..56724f71d37 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/validator/RequestValidator.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/validator/RequestValidator.java
@@ -39,18 +39,19 @@ import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.UnsafeUriCharactersEncoder;
 
 public class RequestValidator {
+
     private static final Pattern REST_PATH_PARAM_PATTERN = Pattern.compile("\\{([^}]+)}");
 
-    private final OpenApiInteractionValidator openApiInteractionValidator;
-    private final RestOpenApiOperation restOpenApiOperation;
-    private final RequestValidationCustomizer requestValidationCustomizer;
+    private final OpenApiInteractionValidator validator;
+    private final RestOpenApiOperation operation;
+    private final RequestValidationCustomizer customizer;
 
-    public RequestValidator(OpenApiInteractionValidator openApiInteractionValidator,
-                            RestOpenApiOperation restOpenApiOperation,
-                            RequestValidationCustomizer requestValidationCustomizer) {
-        this.openApiInteractionValidator = openApiInteractionValidator;
-        this.restOpenApiOperation = restOpenApiOperation;
-        this.requestValidationCustomizer = requestValidationCustomizer;
+    public RequestValidator(OpenApiInteractionValidator validator,
+                            RestOpenApiOperation operation,
+                            RequestValidationCustomizer customizer) {
+        this.validator = validator;
+        this.operation = operation;
+        this.customizer = customizer;
     }
 
     public Set<String> validate(Exchange exchange) {
@@ -63,7 +64,7 @@ public class RequestValidator {
         }
 
         SimpleRequest.Builder builder
-                = new SimpleRequest.Builder(restOpenApiOperation.getMethod(), resolvePathParams(exchange));
+                = new SimpleRequest.Builder(operation.getMethod(), resolvePathParams(exchange));
         builder.withContentType(contentType);
 
         // Validate request body if available
@@ -81,7 +82,7 @@ public class RequestValidator {
         }
 
         // Validate required operation query params
-        restOpenApiOperation.getQueryParams()
+        operation.getQueryParams()
                 .stream()
                 .filter(parameter -> Objects.nonNull(parameter.getRequired()) && parameter.getRequired())
                 .forEach(parameter -> {
@@ -96,7 +97,7 @@ public class RequestValidator {
                 });
 
         // Validate operation required headers
-        restOpenApiOperation.getHeaders()
+        operation.getHeaders()
                 .stream()
                 .filter(parameter -> Objects.nonNull(parameter.getRequired()) && parameter.getRequired())
                 .forEach(parameter -> {
@@ -111,11 +112,11 @@ public class RequestValidator {
                 });
 
         // Apply any extra customizations to the validation request
-        requestValidationCustomizer.customizeSimpleRequestBuilder(builder, restOpenApiOperation, exchange);
+        customizer.customizeSimpleRequestBuilder(builder, operation, exchange);
 
         // Perform validation and capture errors
         Set<String> validationErrors = new LinkedHashSet<>();
-        openApiInteractionValidator.validateRequest(builder.build())
+        validator.validateRequest(builder.build())
                 .getMessages()
                 .stream()
                 .filter(validationMessage -> validationMessage.getLevel().equals(ValidationReport.Level.ERROR))
@@ -129,7 +130,7 @@ public class RequestValidator {
     }
 
     protected String resolvePathParams(Exchange exchange) {
-        String path = restOpenApiOperation.getUriTemplate();
+        String path = operation.getUriTemplate();
         Matcher matcher = REST_PATH_PARAM_PATTERN.matcher(path);
         String pathToProcess = path;
         while (matcher.find()) {


(camel) 12/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f3434923f8f8f293eb2a72841d638a21812ca861
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 10:27:09 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../vertx/PlatformHttpRestOpenApiConsumerTest.java | 56 ++++++++++++++++++++++
 .../rest/openapi/RestOpenApiProcessor.java         | 35 ++++++--------
 2 files changed, 71 insertions(+), 20 deletions(-)

diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
index ab01d018caa..6c9865ecb59 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
@@ -54,4 +54,60 @@ public class PlatformHttpRestOpenApiConsumerTest {
         }
     }
 
+    @Test
+    public void testRestOpenApiNotFound() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("rest-openapi:classpath:openapi-v3.json")
+                            .log("dummy");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .get("/api/v3/pet/123/unknown")
+                    .then()
+                    .statusCode(404);
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testRestOpenApiNotAllowed() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("rest-openapi:classpath:openapi-v3.json")
+                            .log("dummy");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .put("/api/v3/pet/123")
+                    .then()
+                    .statusCode(405);
+        } finally {
+            context.stop();
+        }
+    }
+
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index 283327a3c6a..f0c8bb351a7 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -17,12 +17,11 @@
 package org.apache.camel.component.rest.openapi;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.RejectedExecutionException;
 
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
-import io.swagger.v3.oas.models.PathItem;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
@@ -34,6 +33,9 @@ import org.apache.camel.support.service.ServiceHelper;
 
 public class RestOpenApiProcessor extends DelegateAsyncProcessor implements CamelContextAware {
 
+    private static final List<String> METHODS
+            = Arrays.asList("GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "OPTIONS", "CONNECT", "PATCH");
+
     private CamelContext camelContext;
     private final OpenAPI openAPI;
     private final String basePath;
@@ -68,9 +70,7 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
         // TODO: check if valid operation according to OpenApi
-        // TODO: validate GET/POST etc
         // TODO: RequestValidator
-        // TODO: 404 and so on
         // TODO: binding
 
         String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);
@@ -86,26 +86,21 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
             return restOpenapiProcessorStrategy.process(o, path, exchange, callback);
         }
 
-        // no operation found so it's a 404
-        exchange.setException(new RejectedExecutionException());
-        exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 404);
+        // okay we cannot process this requires so return either 404 or 405.
+        // to know if its 405 then we need to check if any other HTTP method would have a consumer for the "same" request
+        final String contextPath = path;
+        boolean hasAnyMethod
+                = METHODS.stream().anyMatch(v -> RestConsumerContextPathMatcher.matchBestPath(v, contextPath, paths) != null);
+        if (hasAnyMethod) {
+            exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 405);
+        } else {
+            exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 404);
+        }
+        exchange.setRouteStop(true);
         callback.done(true);
         return true;
     }
 
-    protected Operation asOperation(PathItem item, String verb) {
-        return switch (verb) {
-            case "GET" -> item.getGet();
-            case "DELETE" -> item.getDelete();
-            case "HEAD" -> item.getHead();
-            case "PATCH" -> item.getPatch();
-            case "OPTIONS" -> item.getOptions();
-            case "PUT" -> item.getPut();
-            case "POST" -> item.getPost();
-            default -> null;
-        };
-    }
-
     @Override
     protected void doBuild() throws Exception {
         super.doBuild();


(camel) 13/38: CAMEL-20557: Rest DSL to use openapi spec directly

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 38a8961e3514141399ecf6e1e0510c651b1c6b83
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 10:30:39 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java    | 1 -
 1 file changed, 1 deletion(-)

diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index f0c8bb351a7..4cfbccc1839 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -69,7 +69,6 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
 
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
-        // TODO: check if valid operation according to OpenApi
         // TODO: RequestValidator
         // TODO: binding