davsclaus commented on code in PR #27686:
URL: https://github.com/apache/camel/pull/27686#discussion_r4245542301


##########
components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/Kamelet.java:
##########
@@ -230,9 +250,78 @@ public static RouteDefinition 
templateToRoute(RouteTemplateDefinition in, Map<St
             throw new IllegalArgumentException("Camel route " + rid + " input 
does not exist.");
         }
 
+        // Extract advanced options for source/sink component endpoints
+        Map<String, Object> sourceOptions = 
PropertiesHelper.extractProperties(parameters, "source.");
+        Map<String, Object> sinkOptions = 
PropertiesHelper.extractProperties(parameters, "sink.");
+
+        // Determine Kamelet type: source Kamelets have real component as 
input,
+        // sink/action Kamelets have kamelet:source as input and real 
component in outputs
+        boolean isSourceKamelet = 
!isKameletEndpoint(def.getInput().getEndpointUri(), SOURCE_ID);
+
+        if (isSourceKamelet) {
+            // Source Kamelet: real component endpoint is the input
+            if (!sourceOptions.isEmpty()) {
+                try {
+                    String newUri = 
URISupport.appendParametersToURI(def.getInput().getUri(), sourceOptions);
+                    def.getInput().setUri(newUri);
+                } catch (Exception e) {
+                    throw new IllegalArgumentException(
+                            "Failed to apply advanced source options to 
endpoint URI: " + def.getInput().getUri(), e);
+                }
+            }
+            if (!sinkOptions.isEmpty()) {
+                throw new IllegalArgumentException(
+                        "sink.* advanced options are not valid for source 
Kamelets (input is '"
+                                                   + 
def.getInput().getEndpointUri() + "'). Use source.* options instead.");
+            }
+        } else {
+            // Sink/Action Kamelet: real component endpoint(s) are in outputs
+            if (!sourceOptions.isEmpty()) {
+                throw new IllegalArgumentException(
+                        "source.* advanced options are not valid for 
sink/action Kamelets (input is '"
+                                                   + 
def.getInput().getEndpointUri() + "'). Use sink.* options instead.");
+            }
+            if (!sinkOptions.isEmpty()) {
+                Collection<ToDefinition> outputs = 
filterTypeInOutputs(def.getOutputs(), ToDefinition.class);
+                boolean hasRealEndpoint = false;
+                for (ToDefinition to : outputs) {
+                    String uri = to.getEndpointUri();
+                    // Apply to all non-kamelet endpoints (real component 
endpoints)
+                    if (!uri.startsWith("kamelet:")) {

Review Comment:
   This applies `sink.*` to every static non-kamelet `to()`, also ones nested 
in choice/doTry, and e.g. `log:` next to the real endpoint would then fail on 
an unknown option. Should this target only the main sink endpoint?



##########
components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/Kamelet.java:
##########
@@ -230,9 +250,78 @@ public static RouteDefinition 
templateToRoute(RouteTemplateDefinition in, Map<St
             throw new IllegalArgumentException("Camel route " + rid + " input 
does not exist.");
         }
 
+        // Extract advanced options for source/sink component endpoints
+        Map<String, Object> sourceOptions = 
PropertiesHelper.extractProperties(parameters, "source.");

Review Comment:
   The parameters contain each key in both camelCase and kebab-case 
(`DefaultModel.addProperty`), so both forms end up on the endpoint URI. They 
need to be deduplicated to one form.



##########
components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/Kamelet.java:
##########
@@ -230,9 +250,78 @@ public static RouteDefinition 
templateToRoute(RouteTemplateDefinition in, Map<St
             throw new IllegalArgumentException("Camel route " + rid + " input 
does not exist.");
         }
 
+        // Extract advanced options for source/sink component endpoints
+        Map<String, Object> sourceOptions = 
PropertiesHelper.extractProperties(parameters, "source.");
+        Map<String, Object> sinkOptions = 
PropertiesHelper.extractProperties(parameters, "sink.");
+
+        // Determine Kamelet type: source Kamelets have real component as 
input,
+        // sink/action Kamelets have kamelet:source as input and real 
component in outputs
+        boolean isSourceKamelet = 
!isKameletEndpoint(def.getInput().getEndpointUri(), SOURCE_ID);
+
+        if (isSourceKamelet) {
+            // Source Kamelet: real component endpoint is the input
+            if (!sourceOptions.isEmpty()) {
+                try {
+                    String newUri = 
URISupport.appendParametersToURI(def.getInput().getUri(), sourceOptions);

Review Comment:
   `appendParametersToURI` URL-encodes property placeholders (`{{topic}}` → 
`%7B%7Btopic%7D%7D`) and fails with `URISyntaxException` on `RAW({{...}})`, so 
this breaks almost every real kamelet. Please append the parameters as a raw 
string instead (with the override handled per key), and add a test with 
placeholders.



##########
components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/Kamelet.java:
##########
@@ -230,9 +250,78 @@ public static RouteDefinition 
templateToRoute(RouteTemplateDefinition in, Map<St
             throw new IllegalArgumentException("Camel route " + rid + " input 
does not exist.");
         }
 
+        // Extract advanced options for source/sink component endpoints
+        Map<String, Object> sourceOptions = 
PropertiesHelper.extractProperties(parameters, "source.");
+        Map<String, Object> sinkOptions = 
PropertiesHelper.extractProperties(parameters, "sink.");
+
+        // Determine Kamelet type: source Kamelets have real component as 
input,
+        // sink/action Kamelets have kamelet:source as input and real 
component in outputs
+        boolean isSourceKamelet = 
!isKameletEndpoint(def.getInput().getEndpointUri(), SOURCE_ID);
+
+        if (isSourceKamelet) {
+            // Source Kamelet: real component endpoint is the input
+            if (!sourceOptions.isEmpty()) {
+                try {
+                    String newUri = 
URISupport.appendParametersToURI(def.getInput().getUri(), sourceOptions);
+                    def.getInput().setUri(newUri);
+                } catch (Exception e) {
+                    throw new IllegalArgumentException(
+                            "Failed to apply advanced source options to 
endpoint URI: " + def.getInput().getUri(), e);
+                }
+            }
+            if (!sinkOptions.isEmpty()) {
+                throw new IllegalArgumentException(
+                        "sink.* advanced options are not valid for source 
Kamelets (input is '"
+                                                   + 
def.getInput().getEndpointUri() + "'). Use source.* options instead.");
+            }
+        } else {
+            // Sink/Action Kamelet: real component endpoint(s) are in outputs
+            if (!sourceOptions.isEmpty()) {
+                throw new IllegalArgumentException(
+                        "source.* advanced options are not valid for 
sink/action Kamelets (input is '"
+                                                   + 
def.getInput().getEndpointUri() + "'). Use sink.* options instead.");
+            }
+            if (!sinkOptions.isEmpty()) {
+                Collection<ToDefinition> outputs = 
filterTypeInOutputs(def.getOutputs(), ToDefinition.class);
+                boolean hasRealEndpoint = false;
+                for (ToDefinition to : outputs) {
+                    String uri = to.getEndpointUri();
+                    // Apply to all non-kamelet endpoints (real component 
endpoints)
+                    if (!uri.startsWith("kamelet:")) {
+                        try {
+                            String newUri = 
URISupport.appendParametersToURI(uri, sinkOptions);
+                            to.setUri(newUri);
+                            hasRealEndpoint = true;
+                        } catch (Exception e) {
+                            throw new IllegalArgumentException(
+                                    "Failed to apply advanced sink options to 
endpoint URI: " + uri, e);
+                        }
+                    }
+                }
+
+                Collection<ToDynamicDefinition> dynamicOutputs
+                        = filterTypeInOutputs(def.getOutputs(), 
ToDynamicDefinition.class);
+
+                if (!dynamicOutputs.isEmpty()) {
+                    LOG.warn("sink.* advanced options are applied only to 
statically-defined "

Review Comment:
   Static `wireTap` extends `ToDynamicDefinition`, so this warning also fires 
for it, while enrich/pollEnrich are skipped with no warning.



##########
components/camel-kamelet/src/main/docs/kamelet-component.adoc:
##########
@@ -163,6 +163,46 @@ The usage of this Kamelet into a Camel route is going to 
be the same as any othe
 
 WARNING: beware of any potential circular reference you may introduce when 
using chain of Kamelets, in which case, the runtime will likely be idle 
consuming a high amount of resources.
 
+=== Advanced component endpoint options
+
+Kamelets expose a defined set of parameters, but the underlying Camel 
component may support additional endpoint options. You can pass these options 
when using a Kamelet by prefixing them with `source.` or `sink.`, depending on 
the type of Kamelet.
+
+==== Source Kamelets
+
+For source Kamelets, use the `source.` prefix to pass additional options to 
the underlying source component endpoint. The prefix is removed when the 
options are applied to the endpoint URI.
+
+For example:
+
+[source,java]
+----
+from("direct:start")
+    .to("kamelet:my-source/source?source.block=true");
+----
+
+The `/source` path segment is the route ID within the Kamelet template. 
Replace `source` with the actual route ID defined in your Kamelet template.

Review Comment:
   This is not right: the routeId in `kamelet:templateId/routeId` is the id the 
caller gives the created route, not something defined in the Kamelet template. 
I would drop the routeId from both examples (that also avoids the clash with 
route-scoped properties).



##########
components/camel-kamelet/src/main/docs/kamelet-component.adoc:
##########
@@ -163,6 +163,46 @@ The usage of this Kamelet into a Camel route is going to 
be the same as any othe
 
 WARNING: beware of any potential circular reference you may introduce when 
using chain of Kamelets, in which case, the runtime will likely be idle 
consuming a high amount of resources.
 
+=== Advanced component endpoint options
+
+Kamelets expose a defined set of parameters, but the underlying Camel 
component may support additional endpoint options. You can pass these options 
when using a Kamelet by prefixing them with `source.` or `sink.`, depending on 
the type of Kamelet.
+
+==== Source Kamelets
+
+For source Kamelets, use the `source.` prefix to pass additional options to 
the underlying source component endpoint. The prefix is removed when the 
options are applied to the endpoint URI.
+
+For example:
+
+[source,java]
+----
+from("direct:start")
+    .to("kamelet:my-source/source?source.block=true");

Review Comment:
   A source kamelet is consumed with 
`from("kamelet:my-source?source.xxx=...")`, not `.to(...)`. Also `block` is a 
direct producer option, so it is not a good consumer example.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to