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/01/23 15:30:00 UTC

(camel) 10/19: CAMEL-19749: EIPs should make it easy to use together with variables.

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

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

commit 49229c3e8494832120274d2cb750d4cf1e201d73
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Jan 22 17:16:54 2024 +0100

    CAMEL-19749: EIPs should make it easy to use together with variables.
---
 .../org/apache/camel/catalog/models/toD.json       |  12 +-
 .../org/apache/camel/catalog/models/wireTap.json   |  12 +-
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  23 ++
 .../processor/SpringToDynamicVariableTest.java     |  29 +++
 .../spring/processor/ToDynamicVariableTest.xml     |  66 ++++++
 .../org/apache/camel/model/WireTapDefinition.java  |   2 +
 docs/user-manual/modules/ROOT/pages/variables.adoc |   2 +-
 .../dsl/yaml/deserializers/ModelDeserializers.java |  28 ++-
 .../generated/resources/schema/camelYamlDsl.json   |  20 ++
 .../camel/dsl/yaml/ToVariableDynamicTest.groovy    | 255 +++++++++++++++++++++
 10 files changed, 436 insertions(+), 13 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/toD.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/toD.json
index d914a72f257..2f1ff5355c4 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/toD.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/toD.json
@@ -16,10 +16,12 @@
     "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 this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime." },
     "uri": { "index": 3, "kind": "attribute", "displayName": "Uri", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The uri of the endpoint to send to. The uri can be dynamic computed using the org.apache.camel.language.simple.SimpleLanguage expression." },
-    "pattern": { "index": 4, "kind": "attribute", "displayName": "Pattern", "label": "advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the optional ExchangePattern used to invoke this endpoint" },
-    "cacheSize": { "index": 5, "kind": "attribute", "displayName": "Cache Size", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the maximum size used by the org.apache.camel.spi.ProducerCache which is used to cache and reuse producers when using this recipient list, when uris are reused. Beware that when using dynamic endpoints then it affects how well the cache can [...]
-    "ignoreInvalidEndpoint": { "index": 6, "kind": "attribute", "displayName": "Ignore Invalid Endpoint", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore invalid endpoint URIs and skip sending the message." },
-    "allowOptimisedComponents": { "index": 7, "kind": "attribute", "displayName": "Allow Optimised Components", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow components to optimise toD if they are org.apache.camel.spi.SendDynamicAware ." },
-    "autoStartComponents": { "index": 8, "kind": "attribute", "displayName": "Auto Start Components", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to auto startup components when toD is starting up." }
+    "variableSend": { "index": 4, "kind": "attribute", "displayName": "Variable Send", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not on the  [...]
+    "variableReceive": { "index": 5, "kind": "attribute", "displayName": "Variable Receive", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable as the source for the message body to send. This makes it handy to use variables for user data and to easily control what data to use for sending and receiving. Important: When using send variable then the message body is taken from this  [...]
+    "pattern": { "index": 6, "kind": "attribute", "displayName": "Pattern", "label": "advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the optional ExchangePattern used to invoke this endpoint" },
+    "cacheSize": { "index": 7, "kind": "attribute", "displayName": "Cache Size", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the maximum size used by the org.apache.camel.spi.ProducerCache which is used to cache and reuse producers when using this recipient list, when uris are reused. Beware that when using dynamic endpoints then it affects how well the cache can [...]
+    "ignoreInvalidEndpoint": { "index": 8, "kind": "attribute", "displayName": "Ignore Invalid Endpoint", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore invalid endpoint URIs and skip sending the message." },
+    "allowOptimisedComponents": { "index": 9, "kind": "attribute", "displayName": "Allow Optimised Components", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow components to optimise toD if they are org.apache.camel.spi.SendDynamicAware ." },
+    "autoStartComponents": { "index": 10, "kind": "attribute", "displayName": "Auto Start Components", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to auto startup components when toD is starting up." }
   }
 }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/wireTap.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/wireTap.json
index 46d3a6d7432..3681587d368 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/wireTap.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/wireTap.json
@@ -20,10 +20,12 @@
     "onPrepare": { "index": 5, "kind": "attribute", "displayName": "On Prepare", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.Processor", "deprecated": false, "autowired": false, "secret": false, "description": "Uses the Processor when preparing the org.apache.camel.Exchange to be sent. This can be used to deep-clone messages that should be sent, or any custom logic needed before the exchange is sent." },
     "executorService": { "index": 6, "kind": "attribute", "displayName": "Executor Service", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Uses a custom thread pool" },
     "uri": { "index": 7, "kind": "attribute", "displayName": "Uri", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The uri of the endpoint to send to. The uri can be dynamic computed using the org.apache.camel.language.simple.SimpleLanguage expression." },
-    "pattern": { "index": 8, "kind": "attribute", "displayName": "Pattern", "label": "advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the optional ExchangePattern used to invoke this endpoint" },
-    "cacheSize": { "index": 9, "kind": "attribute", "displayName": "Cache Size", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the maximum size used by the org.apache.camel.spi.ProducerCache which is used to cache and reuse producers when using this recipient list, when uris are reused. Beware that when using dynamic endpoints then it affects how well the cache can [...]
-    "ignoreInvalidEndpoint": { "index": 10, "kind": "attribute", "displayName": "Ignore Invalid Endpoint", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore invalid endpoint URIs and skip sending the message." },
-    "allowOptimisedComponents": { "index": 11, "kind": "attribute", "displayName": "Allow Optimised Components", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow components to optimise toD if they are org.apache.camel.spi.SendDynamicAware ." },
-    "autoStartComponents": { "index": 12, "kind": "attribute", "displayName": "Auto Start Components", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to auto startup components when toD is starting up." }
+    "variableSend": { "index": 8, "kind": "attribute", "displayName": "Variable Send", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not on the  [...]
+    "variableReceive": { "index": 9, "kind": "attribute", "displayName": "Variable Receive", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable as the source for the message body to send. This makes it handy to use variables for user data and to easily control what data to use for sending and receiving. Important: When using send variable then the message body is taken from this  [...]
+    "pattern": { "index": 10, "kind": "attribute", "displayName": "Pattern", "label": "advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the optional ExchangePattern used to invoke this endpoint" },
+    "cacheSize": { "index": 11, "kind": "attribute", "displayName": "Cache Size", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the maximum size used by the org.apache.camel.spi.ProducerCache which is used to cache and reuse producers when using this recipient list, when uris are reused. Beware that when using dynamic endpoints then it affects how well the cache ca [...]
+    "ignoreInvalidEndpoint": { "index": 12, "kind": "attribute", "displayName": "Ignore Invalid Endpoint", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore invalid endpoint URIs and skip sending the message." },
+    "allowOptimisedComponents": { "index": 13, "kind": "attribute", "displayName": "Allow Optimised Components", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow components to optimise toD if they are org.apache.camel.spi.SendDynamicAware ." },
+    "autoStartComponents": { "index": 14, "kind": "attribute", "displayName": "Auto Start Components", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to auto startup components when toD is starting up." }
   }
 }
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 a465a963fc8..9360b3518d2 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
@@ -13569,6 +13569,29 @@ Sets the optional ExchangePattern used to invoke this endpoint.
 <![CDATA[
 The uri of the endpoint to send to. The uri can be dynamic computed using the
 org.apache.camel.language.simple.SimpleLanguage expression.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="variableSend" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+To use a variable to store the received message body (only body, not headers). This is handy for easy access to the
+received message body via variables. Important: When using receive variable then the received body is stored only in
+this variable and not on the current org.apache.camel.Message .
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="variableReceive" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+To use a variable as the source for the message body to send. This makes it handy to use variables for user data and to
+easily control what data to use for sending and receiving. Important: When using send variable then the message body is
+taken from this variable instead of the current Message , however the headers from the Message will still be used as
+well. In other words, the variable is used instead of the message body, but everything else is as usual.
 ]]>
             </xs:documentation>
           </xs:annotation>
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringToDynamicVariableTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringToDynamicVariableTest.java
new file mode 100644
index 00000000000..1c834c5c283
--- /dev/null
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringToDynamicVariableTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.spring.processor;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.processor.ToDynamicVariableTest;
+
+import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
+
+public class SpringToDynamicVariableTest extends ToDynamicVariableTest {
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        return createSpringCamelContext(this, "org/apache/camel/spring/processor/ToDynamicVariableTest.xml");
+    }
+}
diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ToDynamicVariableTest.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ToDynamicVariableTest.xml
new file mode 100644
index 00000000000..69cb6510342
--- /dev/null
+++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ToDynamicVariableTest.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+  <!-- START SNIPPET: example -->
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <jmxAgent id="jmx" disabled="true"/>
+    <route>
+      <from uri="direct:send"/>
+      <setVariable name="hello">
+        <simple>Camel</simple>
+      </setVariable>
+      <to uri="mock:before"/>
+      <toD uri="direct:${header.where}" variableSend="hello"/>
+      <to uri="mock:result"/>
+    </route>
+    <route>
+      <from uri="direct:receive"/>
+      <toD uri="direct:${header.where}" variableReceive="bye"/>
+      <to uri="mock:after"/>
+      <setBody>
+        <simple>${variable:bye}</simple>
+      </setBody>
+      <to uri="mock:result"/>
+    </route>
+    <route>
+      <from uri="direct:sendAndReceive"/>
+      <setVariable name="hello">
+        <simple>Camel</simple>
+      </setVariable>
+      <to uri="mock:before"/>
+      <toD uri="direct:${header.where}" variableSend="hello" variableReceive="bye"/>
+      <to uri="mock:result"/>
+    </route>
+    <route>
+      <from uri="direct:foo"/>
+      <transform>
+        <simple>Bye ${body}</simple>
+      </transform>
+    </route>
+  </camelContext>
+  <!-- END SNIPPET: example -->
+
+</beans>
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/WireTapDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/WireTapDefinition.java
index 547f965b14b..5ea132c8068 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/WireTapDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/WireTapDefinition.java
@@ -38,6 +38,8 @@ import org.apache.camel.spi.Metadata;
 public class WireTapDefinition<Type extends ProcessorDefinition<Type>> extends ToDynamicDefinition
         implements ExecutorServiceAwareDefinition<WireTapDefinition<Type>> {
 
+    // TODO: variables due to extending ToDynamic
+
     @XmlTransient
     private ExecutorService executorServiceBean;
     @XmlTransient
diff --git a/docs/user-manual/modules/ROOT/pages/variables.adoc b/docs/user-manual/modules/ROOT/pages/variables.adoc
index da4ec933221..d9e1cc1bab3 100644
--- a/docs/user-manual/modules/ROOT/pages/variables.adoc
+++ b/docs/user-manual/modules/ROOT/pages/variables.adoc
@@ -172,7 +172,7 @@ camel.variable.user-template = resource:file:/etc/user.json
 
 == Using Variables with EIPs
 
-The most commonly used EIPs for sending and receiving messages (`from`, `to`, `toD`, `enrich` and `pollEnrich`) have
+The most commonly used EIPs for sending and receiving messages (`from`, `to`, `toD`, `enrich`, `pollEnrich`, and `wireTap`) have
 first class support for using variables with the message body.
 
 The intention is to make it more convenient and easy to _gather data_ from other systems without any ceremony to keep
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 cab2a31da16..d0bf6091766 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
@@ -18151,7 +18151,9 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "inheritErrorHandler", type = "boolean"),
                     @YamlProperty(name = "parameters", type = "object"),
                     @YamlProperty(name = "pattern", type = "enum:InOnly,InOut", description = "Sets the optional ExchangePattern used to invoke this endpoint", displayName = "Pattern"),
-                    @YamlProperty(name = "uri", type = "string", required = true, description = "The uri of the endpoint to send to. The uri can be dynamic computed using the org.apache.camel.language.simple.SimpleLanguage expression.", displayName = "Uri")
+                    @YamlProperty(name = "uri", type = "string", required = true, description = "The uri of the endpoint to send to. The uri can be dynamic computed using the org.apache.camel.language.simple.SimpleLanguage expression.", displayName = "Uri"),
+                    @YamlProperty(name = "variableReceive", type = "string", description = "To use a variable as the source for the message body to send. This makes it handy to use variables for user data and to easily control what data to use for sending and receiving. Important: When using send variable then the message body is taken from this variable instead of the current Message , however the headers from the Message will still be used as well. In other words, the variable is used  [...]
+                    @YamlProperty(name = "variableSend", type = "string", description = "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not on the current org.apache.camel.Message .", displayName = "Variable Send")
             }
     )
     public static class ToDynamicDefinitionDeserializer extends YamlDeserializerEndpointAwareBase<ToDynamicDefinition> {
@@ -18220,6 +18222,16 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setUri(val);
                     break;
                 }
+                case "variableReceive": {
+                    String val = asText(node);
+                    target.setVariableReceive(val);
+                    break;
+                }
+                case "variableSend": {
+                    String val = asText(node);
+                    target.setVariableSend(val);
+                    break;
+                }
                 case "id": {
                     String val = asText(node);
                     target.setId(val);
@@ -19929,7 +19941,9 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "onPrepare", type = "string", description = "Uses the Processor when preparing the org.apache.camel.Exchange to be sent. This can be used to deep-clone messages that should be sent, or any custom logic needed before the exchange is sent.", displayName = "On Prepare"),
                     @YamlProperty(name = "parameters", type = "object"),
                     @YamlProperty(name = "pattern", type = "enum:InOnly,InOut", description = "Sets the optional ExchangePattern used to invoke this endpoint", displayName = "Pattern"),
-                    @YamlProperty(name = "uri", type = "string", required = true, description = "The uri of the endpoint to send to. The uri can be dynamic computed using the org.apache.camel.language.simple.SimpleLanguage expression.", displayName = "Uri")
+                    @YamlProperty(name = "uri", type = "string", required = true, description = "The uri of the endpoint to send to. The uri can be dynamic computed using the org.apache.camel.language.simple.SimpleLanguage expression.", displayName = "Uri"),
+                    @YamlProperty(name = "variableReceive", type = "string", description = "To use a variable as the source for the message body to send. This makes it handy to use variables for user data and to easily control what data to use for sending and receiving. Important: When using send variable then the message body is taken from this variable instead of the current Message , however the headers from the Message will still be used as well. In other words, the variable is used  [...]
+                    @YamlProperty(name = "variableSend", type = "string", description = "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not on the current org.apache.camel.Message .", displayName = "Variable Send")
             }
     )
     public static class WireTapDefinitionDeserializer extends YamlDeserializerEndpointAwareBase<WireTapDefinition> {
@@ -20013,6 +20027,16 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setUri(val);
                     break;
                 }
+                case "variableReceive": {
+                    String val = asText(node);
+                    target.setVariableReceive(val);
+                    break;
+                }
+                case "variableSend": {
+                    String val = asText(node);
+                    target.setVariableSend(val);
+                    break;
+                }
                 case "id": {
                     String val = asText(node);
                     target.setId(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 6089a141ca4..4f7c733fd1c 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
@@ -6921,6 +6921,16 @@
               "type" : "string",
               "title" : "Uri",
               "description" : "The uri of the endpoint to send to. The uri can be dynamic computed using the org.apache.camel.language.simple.SimpleLanguage expression."
+            },
+            "variableReceive" : {
+              "type" : "string",
+              "title" : "Variable Receive",
+              "description" : "To use a variable as the source for the message body to send. This makes it handy to use variables for user data and to easily control what data to use for sending and receiving. Important: When using send variable then the message body is taken from this variable instead of the current Message , however the headers from the Message will still be used as well. In other words, the variable is used instead of the message body, but everything else is as usual."
+            },
+            "variableSend" : {
+              "type" : "string",
+              "title" : "Variable Send",
+              "description" : "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not on the current org.apache.camel.Message ."
             }
           }
         } ],
@@ -8059,6 +8069,16 @@
             "type" : "string",
             "title" : "Uri",
             "description" : "The uri of the endpoint to send to. The uri can be dynamic computed using the org.apache.camel.language.simple.SimpleLanguage expression."
+          },
+          "variableReceive" : {
+            "type" : "string",
+            "title" : "Variable Receive",
+            "description" : "To use a variable as the source for the message body to send. This makes it handy to use variables for user data and to easily control what data to use for sending and receiving. Important: When using send variable then the message body is taken from this variable instead of the current Message , however the headers from the Message will still be used as well. In other words, the variable is used instead of the message body, but everything else is as usual."
+          },
+          "variableSend" : {
+            "type" : "string",
+            "title" : "Variable Send",
+            "description" : "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not on the current org.apache.camel.Message ."
           }
         },
         "required" : [ "uri" ]
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ToVariableDynamicTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ToVariableDynamicTest.groovy
new file mode 100644
index 00000000000..1112010f449
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ToVariableDynamicTest.groovy
@@ -0,0 +1,255 @@
+/*
+ * 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.dsl.yaml
+
+import org.apache.camel.component.mock.MockEndpoint
+import org.apache.camel.dsl.yaml.support.YamlTestSupport
+
+class ToVariableDynamicTest extends YamlTestSupport {
+
+    def "toDVariable send"() {
+        setup:
+            loadRoutes '''
+                - route:
+                    from:
+                      uri: direct:send
+                      steps:
+                        - setVariable:
+                            name: hello
+                            simple:
+                              expression: Camel
+                        - to:
+                            uri: mock:before
+                        - toD:
+                            uri: direct:${header.where}
+                            variableSend: hello
+                        - to:
+                            uri: mock:result
+                - route:
+                    from:
+                      uri: direct:receive
+                      steps:
+                        - toD:
+                            uri: direct:${header.where}
+                            variableReceive: bye
+                        - to:
+                            uri: mock:after
+                        - setBody:
+                            simple:
+                              expression: "${variable:bye}"
+                        - to:
+                            uri: mock:result
+                - route:
+                    from:
+                      uri: direct:sendAndReceive
+                      steps:
+                        - setVariable:
+                            name: hello
+                            simple:
+                              expression: Camel
+                        - to:
+                            uri: mock:before
+                        - toD:
+                            uri: direct:${header.where}
+                            variableReceive: bye
+                            variableSend: hello
+                        - to:
+                            uri: mock:result
+                - route:
+                    from:
+                      uri: direct:foo
+                      steps:
+                        - transform:
+                            simple:
+                              expression: "Bye ${body}"
+            '''
+
+            withMock('mock:before') {
+                expectedBodiesReceived 'World'
+                expectedVariableReceived("hello", "Camel")
+            }
+            withMock('mock:result') {
+                expectedBodiesReceived 'Bye Camel'
+                expectedVariableReceived("hello", "Camel")
+            }
+
+        when:
+            context.start()
+
+            withTemplate {
+                to('direct:send').withBody('World').withHeader("where", "foo").send()
+            }
+
+        then:
+            MockEndpoint.assertIsSatisfied(context)
+    }
+
+
+    def "toDVariable receive"() {
+        setup:
+        loadRoutes '''
+                - route:
+                    from:
+                      uri: direct:send
+                      steps:
+                        - setVariable:
+                            name: hello
+                            simple:
+                              expression: Camel
+                        - to:
+                            uri: mock:before
+                        - toD:
+                            uri: direct:${header.where}
+                            variableSend: hello
+                        - to:
+                            uri: mock:result
+                - route:
+                    from:
+                      uri: direct:receive
+                      steps:
+                        - toD:
+                            uri: direct:${header.where}
+                            variableReceive: bye
+                        - to:
+                            uri: mock:after
+                        - setBody:
+                            simple:
+                              expression: "${variable:bye}"
+                        - to:
+                            uri: mock:result
+                - route:
+                    from:
+                      uri: direct:sendAndReceive
+                      steps:
+                        - setVariable:
+                            name: hello
+                            simple:
+                              expression: Camel
+                        - to:
+                            uri: mock:before
+                        - toD:
+                            uri: direct:${header.where}
+                            variableReceive: bye
+                            variableSend: hello
+                        - to:
+                            uri: mock:result
+                - route:
+                    from:
+                      uri: direct:foo
+                      steps:
+                        - transform:
+                            simple:
+                              expression: "Bye ${body}"
+            '''
+
+        withMock('mock:after') {
+            expectedBodiesReceived 'World'
+            expectedVariableReceived("bye", "Bye World")
+        }
+        withMock('mock:result') {
+            expectedBodiesReceived 'Bye World'
+            expectedVariableReceived("bye", "Bye World")
+        }
+
+        when:
+        context.start()
+
+        withTemplate {
+            to('direct:receive').withBody('World').withHeader("where", "foo").send()
+        }
+
+        then:
+        MockEndpoint.assertIsSatisfied(context)
+    }
+
+    def "toDVariable sendAndReceive"() {
+        setup:
+        loadRoutes '''
+                - route:
+                    from:
+                      uri: direct:send
+                      steps:
+                        - setVariable:
+                            name: hello
+                            simple:
+                              expression: Camel
+                        - to:
+                            uri: mock:before
+                        - toD:
+                            uri: direct:${header.where}
+                            variableSend: hello
+                        - to:
+                            uri: mock:result
+                - route:
+                    from:
+                      uri: direct:receive
+                      steps:
+                        - toD:
+                            uri: direct:${header.where}
+                            variableReceive: bye
+                        - to:
+                            uri: mock:after
+                        - setBody:
+                            simple:
+                              expression: "${variable:bye}"
+                        - to:
+                            uri: mock:result
+                - route:
+                    from:
+                      uri: direct:sendAndReceive
+                      steps:
+                        - setVariable:
+                            name: hello
+                            simple:
+                              expression: Camel
+                        - to:
+                            uri: mock:before
+                        - toD:
+                            uri: direct:${header.where}
+                            variableReceive: bye
+                            variableSend: hello
+                        - to:
+                            uri: mock:result
+                - route:
+                    from:
+                      uri: direct:foo
+                      steps:
+                        - transform:
+                            simple:
+                              expression: "Bye ${body}"
+            '''
+
+        withMock('mock:before') {
+            expectedBodiesReceived 'World'
+            expectedVariableReceived("hello", "Camel")
+        }
+        withMock('mock:result') {
+            expectedBodiesReceived 'World'
+            expectedVariableReceived("bye", "Bye Camel")
+        }
+
+        when:
+        context.start()
+
+        withTemplate {
+            to('direct:sendAndReceive').withBody('World').withHeader("where", "foo").send()
+        }
+
+        then:
+        MockEndpoint.assertIsSatisfied(context)
+    }
+}