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/02 12:11:14 UTC

(camel) 02/02: CAMEL-20288: camel-core - Convert header and variable To another name

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

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

commit 5abb182ec1df0ca934802c2511fb0f2956f5de68
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Jan 2 13:10:49 2024 +0100

    CAMEL-20288: camel-core - Convert header and variable To another name
---
 .../camel/catalog/models/convertVariableTo.json    |  5 ++-
 .../modules/eips/pages/convertVariableTo-eip.adoc  | 44 ++++++++++++++++++++++
 .../org/apache/camel/model/convertVariableTo.json  |  5 ++-
 .../camel/model/ConvertVariableDefinition.java     | 24 ++++++++++++
 .../apache/camel/model/ProcessorDefinition.java    | 13 +++++++
 .../camel/reifier/ConvertVariableReifier.java      | 14 ++++++-
 .../processor/converter/ConvertVariableTest.java   | 16 ++++++++
 .../mbean/ManagedConvertVariableMBean.java         |  3 ++
 .../management/mbean/ManagedConvertVariable.java   |  5 +++
 .../processor/ConvertVariableProcessor.java        | 16 ++++++--
 .../java/org/apache/camel/xml/in/ModelParser.java  |  1 +
 .../java/org/apache/camel/xml/out/ModelWriter.java |  1 +
 .../org/apache/camel/yaml/out/ModelWriter.java     |  1 +
 .../dsl/yaml/deserializers/ModelDeserializers.java |  6 +++
 .../generated/resources/schema/camelYamlDsl.json   |  5 +++
 .../camel/dsl/yaml/ConvertVariableTest.groovy      | 39 +++++++++++++++++++
 16 files changed, 190 insertions(+), 8 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/convertVariableTo.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/convertVariableTo.json
index ffb99653c99..5463dc826fb 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/convertVariableTo.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/convertVariableTo.json
@@ -17,7 +17,8 @@
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime." },
     "name": { "index": 3, "kind": "attribute", "displayName": "Name", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of variable to convert its value The simple language can be used to define a dynamic evaluated header name to be used. Otherwise a constant name will be used." },
     "type": { "index": 4, "kind": "attribute", "displayName": "Type", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The java type to convert to" },
-    "mandatory": { "index": 5, "kind": "attribute", "displayName": "Mandatory", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "When mandatory then the conversion must return a value (cannot be null), if this is not possible then NoTypeConversionAvailableException is thrown. Setting this to false could mean conversion is not possible and the value is [...]
-    "charset": { "index": 6, "kind": "attribute", "displayName": "Charset", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a specific charset when converting" }
+    "toName": { "index": 5, "kind": "attribute", "displayName": "To Name", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use another variable to store the result. By default, the result is stored in the same variable. This option allows to use another variable. The simple language can be used to define a dynamic evaluated variable name to be used. Otherwise a constant name will be used." },
+    "mandatory": { "index": 6, "kind": "attribute", "displayName": "Mandatory", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "When mandatory then the conversion must return a value (cannot be null), if this is not possible then NoTypeConversionAvailableException is thrown. Setting this to false could mean conversion is not possible and the value is [...]
+    "charset": { "index": 7, "kind": "attribute", "displayName": "Charset", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a specific charset when converting" }
   }
 }
diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/convertVariableTo-eip.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/convertVariableTo-eip.adoc
index 5c53e8bdd34..2d91349f193 100644
--- a/core/camel-core-engine/src/main/docs/modules/eips/pages/convertVariableTo-eip.adoc
+++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/convertVariableTo-eip.adoc
@@ -57,6 +57,50 @@ YAML::
 ----
 ====
 
+=== Convert to another variable
+
+By default, the converted value is replaced in the existing variable. However, you can tell Camel to store the result into another variable,
+such as shown below where the value is stored in the `bar` variable:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("seda:foo")
+  .convertVariableTo("foo", "bar", String.class)
+  .log("The variable content: ${variable.bar}");
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+  <from uri="seda:foo"/>
+  <convertVariableTo name="foo" toName="bar" type="String"/>
+  <log message="The variable content: ${variable.bar}"/>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- from:
+    uri: seda:foo
+    steps:
+      - convertVariableTo:
+          name: foo
+          toName: bar
+          type: String
+      - log:
+          message: "The variable content: ${variable.bar}"
+----
+====
+
+
 === Dynamic variable name
 
 The ConvertVariableTo supports using xref:components:languages:simple-language.adoc[Simple] language for dynamic variable name.
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/convertVariableTo.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/convertVariableTo.json
index ffb99653c99..5463dc826fb 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/convertVariableTo.json
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/convertVariableTo.json
@@ -17,7 +17,8 @@
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime." },
     "name": { "index": 3, "kind": "attribute", "displayName": "Name", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of variable to convert its value The simple language can be used to define a dynamic evaluated header name to be used. Otherwise a constant name will be used." },
     "type": { "index": 4, "kind": "attribute", "displayName": "Type", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The java type to convert to" },
-    "mandatory": { "index": 5, "kind": "attribute", "displayName": "Mandatory", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "When mandatory then the conversion must return a value (cannot be null), if this is not possible then NoTypeConversionAvailableException is thrown. Setting this to false could mean conversion is not possible and the value is [...]
-    "charset": { "index": 6, "kind": "attribute", "displayName": "Charset", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a specific charset when converting" }
+    "toName": { "index": 5, "kind": "attribute", "displayName": "To Name", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use another variable to store the result. By default, the result is stored in the same variable. This option allows to use another variable. The simple language can be used to define a dynamic evaluated variable name to be used. Otherwise a constant name will be used." },
+    "mandatory": { "index": 6, "kind": "attribute", "displayName": "Mandatory", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "When mandatory then the conversion must return a value (cannot be null), if this is not possible then NoTypeConversionAvailableException is thrown. Setting this to false could mean conversion is not possible and the value is [...]
+    "charset": { "index": 7, "kind": "attribute", "displayName": "Charset", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a specific charset when converting" }
   }
 }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/ConvertVariableDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/ConvertVariableDefinition.java
index 8e650af2777..0ee738e598b 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/ConvertVariableDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/ConvertVariableDefinition.java
@@ -40,6 +40,8 @@ public class ConvertVariableDefinition extends NoOutputDefinition<ConvertVariabl
     @XmlAttribute(required = true)
     private String type;
     @XmlAttribute
+    private String toName;
+    @XmlAttribute
     @Metadata(label = "advanced", javaType = "java.lang.Boolean", defaultValue = "true")
     private String mandatory;
     @XmlAttribute
@@ -60,6 +62,13 @@ public class ConvertVariableDefinition extends NoOutputDefinition<ConvertVariabl
         setType(typeClass.getCanonicalName());
     }
 
+    public ConvertVariableDefinition(String name, String toName, Class<?> typeClass) {
+        setName(name);
+        setToName(toName);
+        setTypeClass(typeClass);
+        setType(typeClass.getCanonicalName());
+    }
+
     public ConvertVariableDefinition(String name, Class<?> typeClass, boolean mandatory) {
         setName(name);
         setTypeClass(typeClass);
@@ -103,6 +112,21 @@ public class ConvertVariableDefinition extends NoOutputDefinition<ConvertVariabl
         return name;
     }
 
+    public String getToName() {
+        return toName;
+    }
+
+    /**
+     * To use another variable to store the result. By default, the result is stored in the same variable. This option
+     * allows to use another variable.
+     * <p/>
+     * The <tt>simple</tt> language can be used to define a dynamic evaluated variable name to be used. Otherwise a
+     * constant name will be used.
+     */
+    public void setToName(String toName) {
+        this.toName = toName;
+    }
+
     public String getType() {
         return type;
     }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
index 798ac1caaba..27e520df1ac 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
@@ -2883,6 +2883,19 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
         return asType();
     }
 
+    /**
+     * Converts the variable to the specified type
+     *
+     * @param  name   the variable name
+     * @param  toName to use another variable to store the result
+     * @param  type   the type to convert to
+     * @return        the builder
+     */
+    public Type convertVariableTo(String name, String toName, Class<?> type) {
+        addOutput(new ConvertVariableDefinition(name, toName, type));
+        return asType();
+    }
+
     /**
      * Converts the variable to the specified type
      *
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConvertVariableReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConvertVariableReifier.java
index 15a057b543d..395cf43d695 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConvertVariableReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConvertVariableReifier.java
@@ -43,13 +43,25 @@ public class ConvertVariableReifier extends ProcessorReifier<ConvertVariableDefi
             nameExpr = camelContext.resolveLanguage("constant").createExpression(key);
         }
         nameExpr.init(camelContext);
+
+        String toKey = parseString(definition.getToName());
+        Expression toNameExpr = null;
+        if (toKey != null) {
+            if (LanguageSupport.hasSimpleFunction(toKey)) {
+                toNameExpr = camelContext.resolveLanguage("simple").createExpression(toKey);
+            } else {
+                toNameExpr = camelContext.resolveLanguage("constant").createExpression(toKey);
+            }
+            toNameExpr.init(camelContext);
+        }
+
         Class<?> typeClass = parse(Class.class, or(definition.getTypeClass(), parseString(definition.getType())));
         String charset = validateCharset(parseString(definition.getCharset()));
         boolean mandatory = true;
         if (definition.getMandatory() != null) {
             mandatory = parseBoolean(definition.getMandatory(), true);
         }
-        return new ConvertVariableProcessor(key, nameExpr, typeClass, charset, mandatory);
+        return new ConvertVariableProcessor(key, nameExpr, toKey, toNameExpr, typeClass, charset, mandatory);
     }
 
     public static String validateCharset(String charset) throws UnsupportedCharsetException {
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/converter/ConvertVariableTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/converter/ConvertVariableTest.java
index 0d0564a11d7..0f9724ed120 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/converter/ConvertVariableTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/converter/ConvertVariableTest.java
@@ -104,6 +104,19 @@ public class ConvertVariableTest extends ContextTestSupport {
         assertMockEndpointsSatisfied();
     }
 
+    @Test
+    public void testConvertToName() throws Exception {
+        MockEndpoint result = getMockEndpoint("mock:result");
+        result.expectedVariableReceived("foo", "11");
+        result.expectedVariableReceived("bar", 11);
+        result.message(0).variable("foo").isInstanceOf(String.class);
+        result.message(0).variable("bar").isInstanceOf(Integer.class);
+
+        template.sendBodyAndHeader("direct:bar", null, "foo", "11");
+
+        assertMockEndpointsSatisfied();
+    }
+
     @Test
     public void testConvertToIntegerNotMandatory() throws Exception {
         // mandatory should fail
@@ -224,6 +237,9 @@ public class ConvertVariableTest extends ContextTestSupport {
                         .convertVariableTo("foo", byte[].class, "utf-16").to("mock:result");
                 from("direct:charset3").setVariable("foo", header("foo")).removeHeader("foo")
                         .convertVariableTo("foo", String.class, "utf-16").to("mock:result");
+                from("direct:bar").setVariable("foo", header("foo")).removeHeader("foo")
+                        .convertVariableTo("foo", "bar", Integer.class).to("mock:result");
+
             }
         };
     }
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedConvertVariableMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedConvertVariableMBean.java
index eb515328221..3983f75d88c 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedConvertVariableMBean.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedConvertVariableMBean.java
@@ -23,6 +23,9 @@ public interface ManagedConvertVariableMBean extends ManagedProcessorMBean {
     @ManagedAttribute(description = "The variable name")
     String getName();
 
+    @ManagedAttribute(description = "If the result should be stored in another variable")
+    String getToName();
+
     @ManagedAttribute(description = "The java type to convert to")
     String getType();
 
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConvertVariable.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConvertVariable.java
index ae2929500a6..b8cc1c00530 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConvertVariable.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConvertVariable.java
@@ -36,6 +36,11 @@ public class ManagedConvertVariable extends ManagedProcessor implements ManagedC
         return processor.getName();
     }
 
+    @Override
+    public String getToName() {
+        return processor.getToName();
+    }
+
     @Override
     public String getType() {
         return processor.getType().getCanonicalName();
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/processor/ConvertVariableProcessor.java b/core/camel-support/src/main/java/org/apache/camel/support/processor/ConvertVariableProcessor.java
index 203b9dca517..9287902a0d7 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/processor/ConvertVariableProcessor.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/processor/ConvertVariableProcessor.java
@@ -47,15 +47,20 @@ public class ConvertVariableProcessor extends ServiceSupport
     private String routeId;
     private final String name;
     private final Expression variableName;
+    private final String toName;
+    private final Expression toVariableName;
     private final Class<?> type;
     private final String charset;
     private final boolean mandatory;
 
-    public ConvertVariableProcessor(String name, Expression variableName, Class<?> type, String charset, boolean mandatory) {
+    public ConvertVariableProcessor(String name, Expression variableName, String toName, Expression toVariableName,
+                                    Class<?> type, String charset, boolean mandatory) {
         ObjectHelper.notNull(variableName, "variableName");
         ObjectHelper.notNull(type, "type", this);
         this.name = name;
         this.variableName = variableName;
+        this.toName = toName;
+        this.toVariableName = toVariableName;
         this.type = type;
         this.charset = IOHelper.normalizeCharset(charset);
         this.mandatory = mandatory;
@@ -101,6 +106,7 @@ public class ConvertVariableProcessor extends ServiceSupport
         // what is the variable name
         String name = variableName.evaluate(exchange, String.class);
         String key = name;
+        String targetName = toVariableName != null ? toVariableName.evaluate(exchange, String.class) : name;
 
         VariableRepository repo = null;
         Object value;
@@ -137,9 +143,9 @@ public class ConvertVariableProcessor extends ServiceSupport
         }
 
         if (repo != null) {
-            repo.setVariable(key, value);
+            repo.setVariable(targetName, value);
         } else {
-            exchange.setVariable(key, value);
+            exchange.setVariable(targetName, value);
         }
 
         // remove or restore charset when we are done as we should not propagate that,
@@ -175,6 +181,10 @@ public class ConvertVariableProcessor extends ServiceSupport
         return name;
     }
 
+    public String getToName() {
+        return toName;
+    }
+
     public Class<?> getType() {
         return type;
     }
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index 8bb83fd7070..619765f2b6a 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -331,6 +331,7 @@ public class ModelParser extends BaseParser {
                 case "charset": def.setCharset(val); break;
                 case "mandatory": def.setMandatory(val); break;
                 case "name": def.setName(val); break;
+                case "toName": def.setToName(val); break;
                 case "type": def.setType(val); break;
                 default: return processorDefinitionAttributeHandler().accept(def, key, val);
             }
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index 3a838680d24..3c09b466f42 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -1201,6 +1201,7 @@ public class ModelWriter extends BaseWriter {
         startElement(name);
         doWriteProcessorDefinitionAttributes(def);
         doWriteAttribute("charset", def.getCharset());
+        doWriteAttribute("toName", def.getToName());
         doWriteAttribute("name", def.getName());
         doWriteAttribute("type", def.getType());
         doWriteAttribute("mandatory", def.getMandatory());
diff --git a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index 4dadf86af71..312d4b3fba2 100644
--- a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++ b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -1201,6 +1201,7 @@ public class ModelWriter extends BaseWriter {
         startElement(name);
         doWriteProcessorDefinitionAttributes(def);
         doWriteAttribute("charset", def.getCharset());
+        doWriteAttribute("toName", def.getToName());
         doWriteAttribute("name", def.getName());
         doWriteAttribute("type", def.getType());
         doWriteAttribute("mandatory", def.getMandatory());
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 d74e84bd92d..a14e2849863 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
@@ -2673,6 +2673,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "inheritErrorHandler", type = "boolean"),
                     @YamlProperty(name = "mandatory", type = "boolean", description = "When mandatory then the conversion must return a value (cannot be null), if this is not possible then NoTypeConversionAvailableException is thrown. Setting this to false could mean conversion is not possible and the value is null.", displayName = "Mandatory"),
                     @YamlProperty(name = "name", type = "string", required = true, description = "Name of variable to convert its value The simple language can be used to define a dynamic evaluated header name to be used. Otherwise a constant name will be used.", displayName = "Name"),
+                    @YamlProperty(name = "toName", type = "string", description = "To use another variable to store the result. By default, the result is stored in the same variable. This option allows to use another variable. The simple language can be used to define a dynamic evaluated variable name to be used. Otherwise a constant name will be used.", displayName = "To Name"),
                     @YamlProperty(name = "type", type = "string", required = true, description = "The java type to convert to", displayName = "Type")
             }
     )
@@ -2716,6 +2717,11 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setName(val);
                     break;
                 }
+                case "toName": {
+                    String val = asText(node);
+                    target.setToName(val);
+                    break;
+                }
                 case "type": {
                     String val = asText(node);
                     target.setType(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 2a1fb08c1cd..df5d2b48600 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
@@ -896,6 +896,11 @@
             "title" : "Name",
             "description" : "Name of variable to convert its value The simple language can be used to define a dynamic evaluated header name to be used. Otherwise a constant name will be used."
           },
+          "toName" : {
+            "type" : "string",
+            "title" : "To Name",
+            "description" : "To use another variable to store the result. By default, the result is stored in the same variable. This option allows to use another variable. The simple language can be used to define a dynamic evaluated variable name to be used. Otherwise a constant name will be used."
+          },
           "type" : {
             "type" : "string",
             "title" : "Type",
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ConvertVariableTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ConvertVariableTest.groovy
index 6f8436077be..637c0aa1886 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ConvertVariableTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ConvertVariableTest.groovy
@@ -61,6 +61,45 @@ class ConvertVariableTest extends YamlTestSupport {
             MockEndpoint.assertIsSatisfied(context)
     }
 
+    def "convert-variable-another-to"() {
+        setup:
+        loadRoutes '''
+                - from:
+                    uri: "direct:start"
+                    steps:
+                      - setVariable:
+                          name: foo
+                          constant: "Hello World"
+                      - convertVariableTo:
+                          name: foo
+                          toName: bar
+                          type: "java.lang.String"
+                          charset: "UTF8"
+                      - to: "mock:result"
+            '''
+
+        withMock('mock:result') {
+            expectedVariableReceived("foo", 'Hello World')
+        }
+        when:
+        context.start()
+
+        withTemplate {
+            to('direct:start').withHeader("foo", 'test'.bytes).send()
+        }
+        then:
+        context.routeDefinitions.size() == 1
+
+        with(context.routeDefinitions[0].outputs[1], ConvertVariableDefinition) {
+            name == 'foo'
+            toName == 'bar'
+            type == 'java.lang.String'
+            charset == 'UTF8'
+        }
+
+        MockEndpoint.assertIsSatisfied(context)
+    }
+
     def "Error: kebab-case: convert-variable-to"() {
         when:
         var route = '''