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 <claus.ib...@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;
 }

Reply via email to