You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2021/04/13 05:15:44 UTC

[camel] branch master updated: Yaml DSL: fix backward compatibility issues (CAMEL-16489, CAMEL-16490)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 008d4d3  Yaml DSL: fix backward compatibility issues (CAMEL-16489, CAMEL-16490)
008d4d3 is described below

commit 008d4d3189de51bc6e93333c2c51e6be0ba364b1
Author: Luca Burgazzoli <lb...@gmail.com>
AuthorDate: Mon Apr 12 18:34:24 2021 +0200

    Yaml DSL: fix backward compatibility issues (CAMEL-16489, CAMEL-16490)
---
 .../common/YamlDeserializerEndpointAwareBase.java  |  70 ++++++++++++
 .../dsl/yaml/deserializers/ModelDeserializers.java | 119 ++++++++-----------
 .../deserializers/ModelDeserializersResolver.java  |   1 +
 .../dsl/yaml/GenerateYamlDeserializersMojo.java    |  63 +++++++----
 .../maven/dsl/yaml/GenerateYamlSupportMojo.java    |   2 +
 .../maven/dsl/yaml/support/TypeSpecHolder.java     |  10 +-
 .../src/generated/resources/camel-yaml-dsl.json    |   3 +
 .../org/apache/camel/dsl/yaml/SagaTest.groovy      |  46 ++++++++
 .../org/apache/camel/dsl/yaml/ToDynamicTest.groovy | 126 +++++++++++++++++++++
 .../groovy/org/apache/camel/dsl/yaml/ToTest.groovy |  11 +-
 10 files changed, 360 insertions(+), 91 deletions(-)

diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-common/src/main/java/org/apache/camel/dsl/yaml/common/YamlDeserializerEndpointAwareBase.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-common/src/main/java/org/apache/camel/dsl/yaml/common/YamlDeserializerEndpointAwareBase.java
new file mode 100644
index 0000000..c5ce979
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-common/src/main/java/org/apache/camel/dsl/yaml/common/YamlDeserializerEndpointAwareBase.java
@@ -0,0 +1,70 @@
+/*
+ * 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.common;
+
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.util.StringHelper;
+import org.snakeyaml.engine.v2.nodes.MappingNode;
+import org.snakeyaml.engine.v2.nodes.Node;
+import org.snakeyaml.engine.v2.nodes.NodeTuple;
+import org.snakeyaml.engine.v2.nodes.ScalarNode;
+
+public abstract class YamlDeserializerEndpointAwareBase<T> extends YamlDeserializerBase<T> {
+
+    public YamlDeserializerEndpointAwareBase(Class<T> type) {
+        super(type);
+    }
+
+    /**
+     * Set properties from a YAML node to the given target.
+     *
+     * @param node   the node
+     * @param target the target object
+     */
+    protected void setProperties(T target, MappingNode node) {
+        YamlDeserializationContext dc = getDeserializationContext(node);
+
+        Map<String, Object> parameters = null;
+
+        for (NodeTuple tuple : node.getValue()) {
+            final ScalarNode key = (ScalarNode) tuple.getKeyNode();
+            final String propertyName = StringHelper.camelCaseToDash(key.getValue()).toLowerCase(Locale.US);
+            final Node val = tuple.getValueNode();
+
+            setDeserializationContext(val, dc);
+
+            switch (propertyName) {
+                case "parameters":
+                    parameters = asScalarMap(tuple.getValueNode());
+                    break;
+                default:
+                    if (!setProperty(target, propertyName, key.getValue(), val)) {
+                        handleUnknownProperty(target, propertyName, key.getValue(), val);
+                    }
+            }
+        }
+
+        if (parameters != null) {
+            setEndpointUri(dc.getCamelContext(), target, parameters);
+        }
+    }
+
+    protected abstract void setEndpointUri(CamelContext context, T target, Map<String, Object> parameters);
+}
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 4826e21..b21ffb1 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
@@ -1,12 +1,14 @@
 // Generated by camel-yaml-dsl-maven-plugin - do NOT edit this file!
 package org.apache.camel.dsl.yaml.deserializers;
 
+import java.lang.Object;
 import java.lang.Override;
 import java.lang.String;
-import org.apache.camel.dsl.yaml.common.YamlDeserializationContext;
+import java.util.Map;
+import org.apache.camel.CamelContext;
 import org.apache.camel.dsl.yaml.common.YamlDeserializerBase;
+import org.apache.camel.dsl.yaml.common.YamlDeserializerEndpointAwareBase;
 import org.apache.camel.dsl.yaml.common.YamlDeserializerSupport;
-import org.apache.camel.dsl.yaml.common.YamlSupport;
 import org.apache.camel.model.AggregateDefinition;
 import org.apache.camel.model.BeanDefinition;
 import org.apache.camel.model.CatchDefinition;
@@ -5881,7 +5883,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "parameters", type = "object")
             }
     )
-    public static class InOnlyDefinitionDeserializer extends YamlDeserializerBase<InOnlyDefinition> {
+    public static class InOnlyDefinitionDeserializer extends YamlDeserializerEndpointAwareBase<InOnlyDefinition> {
         public InOnlyDefinitionDeserializer() {
             super(InOnlyDefinition.class);
         }
@@ -5897,6 +5899,12 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
 
         @Override
+        protected void setEndpointUri(CamelContext camelContext, InOnlyDefinition target,
+                Map<String, Object> parameters) {
+            target.setUri(org.apache.camel.dsl.yaml.common.YamlSupport.createEndpointUri(camelContext, target.getUri(), parameters));
+        }
+
+        @Override
         protected boolean setProperty(InOnlyDefinition target, String propertyKey,
                 String propertyName, Node node) {
             switch(propertyKey) {
@@ -5910,16 +5918,6 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setUri(val);
                     break;
                 }
-                case "parameters": {
-                    if (target.getUri() == null) {
-                        throw new IllegalStateException("url must be set before setting parameters");
-                    }
-                    java.util.Map<String, Object> parameters = asScalarMap(asMappingNode(node));
-                    YamlDeserializationContext dc = getDeserializationContext(node);
-                    String uri = YamlSupport.createEndpointUri(dc.getCamelContext(), target.getUri(), parameters);
-                    target.setUri(uri);
-                    break;
-                }
                 default: {
                     String uri = EndpointProducerDeserializersResolver.resolveEndpointUri(propertyKey, node);
                     if (uri == null) {
@@ -5946,7 +5944,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "parameters", type = "object")
             }
     )
-    public static class InOutDefinitionDeserializer extends YamlDeserializerBase<InOutDefinition> {
+    public static class InOutDefinitionDeserializer extends YamlDeserializerEndpointAwareBase<InOutDefinition> {
         public InOutDefinitionDeserializer() {
             super(InOutDefinition.class);
         }
@@ -5962,6 +5960,12 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
 
         @Override
+        protected void setEndpointUri(CamelContext camelContext, InOutDefinition target,
+                Map<String, Object> parameters) {
+            target.setUri(org.apache.camel.dsl.yaml.common.YamlSupport.createEndpointUri(camelContext, target.getUri(), parameters));
+        }
+
+        @Override
         protected boolean setProperty(InOutDefinition target, String propertyKey,
                 String propertyName, Node node) {
             switch(propertyKey) {
@@ -5975,16 +5979,6 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setUri(val);
                     break;
                 }
-                case "parameters": {
-                    if (target.getUri() == null) {
-                        throw new IllegalStateException("url must be set before setting parameters");
-                    }
-                    java.util.Map<String, Object> parameters = asScalarMap(asMappingNode(node));
-                    YamlDeserializationContext dc = getDeserializationContext(node);
-                    String uri = YamlSupport.createEndpointUri(dc.getCamelContext(), target.getUri(), parameters);
-                    target.setUri(uri);
-                    break;
-                }
                 default: {
                     String uri = EndpointProducerDeserializersResolver.resolveEndpointUri(propertyKey, node);
                     if (uri == null) {
@@ -11826,7 +11820,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "parameters", type = "object")
             }
     )
-    public static class SagaActionUriDefinitionDeserializer extends YamlDeserializerBase<SagaActionUriDefinition> {
+    public static class SagaActionUriDefinitionDeserializer extends YamlDeserializerEndpointAwareBase<SagaActionUriDefinition> {
         public SagaActionUriDefinitionDeserializer() {
             super(SagaActionUriDefinition.class);
         }
@@ -11842,6 +11836,12 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
 
         @Override
+        protected void setEndpointUri(CamelContext camelContext, SagaActionUriDefinition target,
+                Map<String, Object> parameters) {
+            target.setUri(org.apache.camel.dsl.yaml.common.YamlSupport.createEndpointUri(camelContext, target.getUri(), parameters));
+        }
+
+        @Override
         protected boolean setProperty(SagaActionUriDefinition target, String propertyKey,
                 String propertyName, Node node) {
             switch(propertyKey) {
@@ -11855,16 +11855,6 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setUri(val);
                     break;
                 }
-                case "parameters": {
-                    if (target.getUri() == null) {
-                        throw new IllegalStateException("url must be set before setting parameters");
-                    }
-                    java.util.Map<String, Object> parameters = asScalarMap(asMappingNode(node));
-                    YamlDeserializationContext dc = getDeserializationContext(node);
-                    String uri = YamlSupport.createEndpointUri(dc.getCamelContext(), target.getUri(), parameters);
-                    target.setUri(uri);
-                    break;
-                }
                 default: {
                     String uri = EndpointProducerDeserializersResolver.resolveEndpointUri(propertyKey, node);
                     if (uri == null) {
@@ -14156,7 +14146,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "parameters", type = "object")
             }
     )
-    public static class ToDefinitionDeserializer extends YamlDeserializerBase<ToDefinition> {
+    public static class ToDefinitionDeserializer extends YamlDeserializerEndpointAwareBase<ToDefinition> {
         public ToDefinitionDeserializer() {
             super(ToDefinition.class);
         }
@@ -14172,6 +14162,12 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
 
         @Override
+        protected void setEndpointUri(CamelContext camelContext, ToDefinition target,
+                Map<String, Object> parameters) {
+            target.setUri(org.apache.camel.dsl.yaml.common.YamlSupport.createEndpointUri(camelContext, target.getUri(), parameters));
+        }
+
+        @Override
         protected boolean setProperty(ToDefinition target, String propertyKey, String propertyName,
                 Node node) {
             switch(propertyKey) {
@@ -14190,16 +14186,6 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setUri(val);
                     break;
                 }
-                case "parameters": {
-                    if (target.getUri() == null) {
-                        throw new IllegalStateException("url must be set before setting parameters");
-                    }
-                    java.util.Map<String, Object> parameters = asScalarMap(asMappingNode(node));
-                    YamlDeserializationContext dc = getDeserializationContext(node);
-                    String uri = YamlSupport.createEndpointUri(dc.getCamelContext(), target.getUri(), parameters);
-                    target.setUri(uri);
-                    break;
-                }
                 default: {
                     String uri = EndpointProducerDeserializersResolver.resolveEndpointUri(propertyKey, node);
                     if (uri == null) {
@@ -14219,7 +14205,10 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
             inline = true,
             types = org.apache.camel.model.ToDynamicDefinition.class,
             order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
-            nodes = "to-d",
+            nodes = {
+                    "to-d",
+                    "tod"
+            },
             properties = {
                     @YamlProperty(name = "allow-optimised-components", type = "boolean"),
                     @YamlProperty(name = "auto-start-components", type = "boolean"),
@@ -14231,7 +14220,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "parameters", type = "object")
             }
     )
-    public static class ToDynamicDefinitionDeserializer extends YamlDeserializerBase<ToDynamicDefinition> {
+    public static class ToDynamicDefinitionDeserializer extends YamlDeserializerEndpointAwareBase<ToDynamicDefinition> {
         public ToDynamicDefinitionDeserializer() {
             super(ToDynamicDefinition.class);
         }
@@ -14247,6 +14236,12 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
 
         @Override
+        protected void setEndpointUri(CamelContext camelContext, ToDynamicDefinition target,
+                Map<String, Object> parameters) {
+            target.setUri(org.apache.camel.dsl.yaml.common.YamlSupport.createEndpointUri(camelContext, target.getUri(), parameters));
+        }
+
+        @Override
         protected boolean setProperty(ToDynamicDefinition target, String propertyKey,
                 String propertyName, Node node) {
             switch(propertyKey) {
@@ -14285,16 +14280,6 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setUri(val);
                     break;
                 }
-                case "parameters": {
-                    if (target.getUri() == null) {
-                        throw new IllegalStateException("url must be set before setting parameters");
-                    }
-                    java.util.Map<String, Object> parameters = asScalarMap(asMappingNode(node));
-                    YamlDeserializationContext dc = getDeserializationContext(node);
-                    String uri = YamlSupport.createEndpointUri(dc.getCamelContext(), target.getUri(), parameters);
-                    target.setUri(uri);
-                    break;
-                }
                 default: {
                     String uri = EndpointProducerDeserializersResolver.resolveEndpointUri(propertyKey, node);
                     if (uri == null) {
@@ -15875,7 +15860,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "parameters", type = "object")
             }
     )
-    public static class WireTapDefinitionDeserializer extends YamlDeserializerBase<WireTapDefinition> {
+    public static class WireTapDefinitionDeserializer extends YamlDeserializerEndpointAwareBase<WireTapDefinition> {
         public WireTapDefinitionDeserializer() {
             super(WireTapDefinition.class);
         }
@@ -15886,6 +15871,12 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
 
         @Override
+        protected void setEndpointUri(CamelContext camelContext, WireTapDefinition target,
+                Map<String, Object> parameters) {
+            target.setUri(org.apache.camel.dsl.yaml.common.YamlSupport.createEndpointUri(camelContext, target.getUri(), parameters));
+        }
+
+        @Override
         protected boolean setProperty(WireTapDefinition target, String propertyKey,
                 String propertyName, Node node) {
             switch(propertyKey) {
@@ -15959,16 +15950,6 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setUri(val);
                     break;
                 }
-                case "parameters": {
-                    if (target.getUri() == null) {
-                        throw new IllegalStateException("url must be set before setting parameters");
-                    }
-                    java.util.Map<String, Object> parameters = asScalarMap(asMappingNode(node));
-                    YamlDeserializationContext dc = getDeserializationContext(node);
-                    String uri = YamlSupport.createEndpointUri(dc.getCamelContext(), target.getUri(), parameters);
-                    target.setUri(uri);
-                    break;
-                }
                 default: {
                     String uri = EndpointProducerDeserializersResolver.resolveEndpointUri(propertyKey, node);
                     if (uri == null) {
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index 34de60b..0a1741b 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -373,6 +373,7 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "to": return new ModelDeserializers.ToDefinitionDeserializer();
             case "org.apache.camel.model.ToDefinition": return new ModelDeserializers.ToDefinitionDeserializer();
             case "to-d": return new ModelDeserializers.ToDynamicDefinitionDeserializer();
+            case "tod": return new ModelDeserializers.ToDynamicDefinitionDeserializer();
             case "org.apache.camel.model.ToDynamicDefinition": return new ModelDeserializers.ToDynamicDefinitionDeserializer();
             case "tokenize": return new ModelDeserializers.TokenizerExpressionDeserializer();
             case "org.apache.camel.model.language.TokenizerExpression": return new ModelDeserializers.TokenizerExpressionDeserializer();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/GenerateYamlDeserializersMojo.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/GenerateYamlDeserializersMojo.java
index bad935b..a88d4dd 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/GenerateYamlDeserializersMojo.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/GenerateYamlDeserializersMojo.java
@@ -40,6 +40,7 @@ import com.squareup.javapoet.MethodSpec;
 import com.squareup.javapoet.ParameterizedTypeName;
 import com.squareup.javapoet.TypeName;
 import com.squareup.javapoet.TypeSpec;
+import org.apache.camel.CamelContext;
 import org.apache.camel.catalog.CamelCatalog;
 import org.apache.camel.catalog.DefaultCamelCatalog;
 import org.apache.camel.maven.dsl.yaml.support.ToolingSupport;
@@ -299,12 +300,14 @@ public class GenerateYamlDeserializersMojo extends GenerateYamlSupportMojo {
                     deserializers.addType(holder.type);
 
                     if (holder.attributes.containsKey("node")) {
-                        constructors.addStatement(
-                            "case $S: return new ModelDeserializers.$L()", holder.attributes.get("node"), holder.type.name);
+                        holder.attributes.get("node").forEach(node ->
+                            constructors.addStatement(
+                                "case $S: return new ModelDeserializers.$L()", node, holder.type.name));
                     }
                     if (holder.attributes.containsKey("type")) {
-                        constructors.addStatement(
-                            "case $S: return new ModelDeserializers.$L()", holder.attributes.get("type"), holder.type.name);
+                        holder.attributes.get("type").forEach(type ->
+                            constructors.addStatement(
+                                "case $S: return new ModelDeserializers.$L()", type, holder.type.name));
                     }
                 }
             );
@@ -412,13 +415,20 @@ public class GenerateYamlDeserializersMojo extends GenerateYamlSupportMojo {
     private TypeSpecHolder generateParser(ClassInfo info) {
         final ClassName targetType = ClassName.get(info.name().prefix().toString(), info.name().withoutPackagePrefix());
         final TypeSpec.Builder builder = TypeSpec.classBuilder(info.simpleName() + "Deserializer");
-        final Map<String, String> attributes = new HashMap<>();
+        final Map<String, Set<String>> attributes = new HashMap<>();
         final List<AnnotationSpec> properties = new ArrayList<>();
         final AnnotationSpec.Builder yamlTypeAnnotation = AnnotationSpec.builder(CN_YAML_TYPE);
 
         builder.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
-        builder.superclass(ParameterizedTypeName.get(CN_DESERIALIZER_BASE, targetType));
-        attributes.put("type", info.name().toString());
+
+
+        if (extendsType(info, SEND_DEFINITION_CLASS) || extendsType(info, TO_DYNAMIC_DEFINITION_CLASS)) {
+            builder.superclass(ParameterizedTypeName.get(CN_ENDPOINT_AWARE_DESERIALIZER_BASE, targetType));
+        } else {
+            builder.superclass(ParameterizedTypeName.get(CN_DESERIALIZER_BASE, targetType));
+        }
+
+        TypeSpecHolder.put(attributes, "type", info.name().toString());
 
         //TODO: add an option on Camel's definitions to distinguish between IN/OUT types
         if (info.name().toString().equals("org.apache.camel.model.OnExceptionDefinition")) {
@@ -501,17 +511,6 @@ public class GenerateYamlDeserializersMojo extends GenerateYamlSupportMojo {
         }
 
         if (extendsType(info, SEND_DEFINITION_CLASS) || extendsType(info, TO_DYNAMIC_DEFINITION_CLASS)) {
-            setProperty.beginControlFlow("case $S:", "parameters");
-            setProperty.beginControlFlow("if (target.getUri() == null)");
-            setProperty.addStatement("throw new IllegalStateException(\"url must be set before setting parameters\")");
-            setProperty.endControlFlow();
-            setProperty.addStatement("java.util.Map<String, Object> parameters = asScalarMap(asMappingNode(node))");
-            setProperty.addStatement("$T dc = getDeserializationContext(node)", CN_DESERIALIZATION_CONTEXT);
-            setProperty.addStatement("String uri = $T.createEndpointUri(dc.getCamelContext(), target.getUri(), parameters)", CN_YAML_SUPPORT);
-            setProperty.addStatement("target.setUri(uri)");
-            setProperty.addStatement("break");
-            setProperty.endControlFlow();
-
             setProperty.beginControlFlow("default:");
             setProperty.addStatement("String uri = EndpointProducerDeserializersResolver.resolveEndpointUri(propertyKey, node)");
             setProperty.beginControlFlow("if (uri == null)");
@@ -528,6 +527,23 @@ public class GenerateYamlDeserializersMojo extends GenerateYamlSupportMojo {
                     "parameters",
                     "object")
             );
+
+            builder.addMethod(MethodSpec.methodBuilder("setEndpointUri")
+                .addAnnotation(AnnotationSpec.builder(Override.class).build())
+                .addModifiers(Modifier.PROTECTED)
+                .addParameter(CamelContext.class, "camelContext")
+                .addParameter(targetType, "target")
+                .addParameter(
+                    ParameterizedTypeName.get(
+                        ClassName.get(Map.class),
+                        ClassName.get(String.class),
+                        ClassName.get(Object.class)),
+                    "parameters")
+                .addCode(
+                    CodeBlock.builder()
+                        .addStatement("target.setUri(org.apache.camel.dsl.yaml.common.YamlSupport.createEndpointUri(camelContext, target.getUri(), parameters))")
+                        .build())
+                .build());
         } else if (implementType(info, HAS_EXPRESSION_TYPE_CLASS)) {
             setProperty.beginControlFlow("default:");
             setProperty.addStatement("$T ed = target.getExpressionType()", CN_EXPRESSION_DEFINITION);
@@ -585,9 +601,18 @@ public class GenerateYamlDeserializersMojo extends GenerateYamlSupportMojo {
             .map(StringHelper::camelCaseToDash)
             .ifPresent(v -> {
                 yamlTypeAnnotation.addMember("nodes", "$S", v);
-                attributes.put("node", v);
+                TypeSpecHolder.put(attributes, "node", v);
             });
 
+        //
+        // Workaround for:
+        //     https://issues.apache.org/jira/browse/CAMEL-16490
+        //
+        if (info.name().equals(TO_DYNAMIC_DEFINITION_CLASS)) {
+            yamlTypeAnnotation.addMember("nodes", "$S", "tod");
+            TypeSpecHolder.put(attributes, "node", "tod");
+        }
+
         for (AnnotationSpec spec: properties) {
             yamlTypeAnnotation.addMember("properties", "$L", spec);
         }
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/GenerateYamlSupportMojo.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/GenerateYamlSupportMojo.java
index 3be1a50..8e284b8 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/GenerateYamlSupportMojo.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/GenerateYamlSupportMojo.java
@@ -114,6 +114,8 @@ public abstract class GenerateYamlSupportMojo extends AbstractMojo {
             = ClassName.get("org.apache.camel.dsl.yaml.common", "YamlDeserializerSupport");
     public static final ClassName CN_DESERIALIZER_BASE
             = ClassName.get("org.apache.camel.dsl.yaml.common", "YamlDeserializerBase");
+    public static final ClassName CN_ENDPOINT_AWARE_DESERIALIZER_BASE
+        = ClassName.get("org.apache.camel.dsl.yaml.common", "YamlDeserializerEndpointAwareBase");
     public static final ClassName CN_DESERIALIZATION_CONTEXT
             = ClassName.get("org.apache.camel.dsl.yaml.common", "YamlDeserializationContext");
     public static final ClassName CN_YAML_SUPPORT
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/TypeSpecHolder.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/TypeSpecHolder.java
index be78859..6f5ff76 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/TypeSpecHolder.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/TypeSpecHolder.java
@@ -19,18 +19,24 @@ package org.apache.camel.maven.dsl.yaml.support;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
 
 import com.squareup.javapoet.TypeSpec;
 
 public class TypeSpecHolder {
     public final TypeSpec type;
-    public final Map<String, String> attributes;
+    public final Map<String, Set<String>> attributes;
 
-    public TypeSpecHolder(TypeSpec type, Map<String, String> attributes) {
+    public TypeSpecHolder(TypeSpec type, Map<String, Set<String>> attributes) {
         Objects.requireNonNull(type, "type");
         Objects.requireNonNull(attributes, "attributes");
 
         this.type = type;
         this.attributes = new HashMap<>(attributes);
     }
+
+    public static void put(Map<String, Set<String>> attributes, String key, String value) {
+        attributes.computeIfAbsent(key, k -> new TreeSet<>()).add(value);
+    }
 }
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
index 821b910..31b288c 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
@@ -170,6 +170,9 @@
           "to-d" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.ToDynamicDefinition"
           },
+          "tod" : {
+            "$ref" : "#/items/definitions/org.apache.camel.model.ToDynamicDefinition"
+          },
           "transacted" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.TransactedDefinition"
           },
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/SagaTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/SagaTest.groovy
index 8ead82b..74c1ba2 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/SagaTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/SagaTest.groovy
@@ -81,6 +81,52 @@ class SagaTest extends YamlTestSupport {
                                    simple: "${body}"        
                           - to: "mock:result"
                     '''),
+                asResource('full-parameters', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - saga:  
+                             propagation: "MANDATORY"
+                             completion-mode: "MANUAL"
+                             compensation: 
+                                 uri: "direct"
+                                 parameters:
+                                   name: compensation
+                             completion:
+                                 uri: "direct:completion"
+                             steps:
+                               - to: "direct:something"
+                             option:
+                               - option-name: o1
+                                 simple: "${body}" 
+                               - option-name: o2
+                                 expression:
+                                   simple: "${body}"        
+                          - to: "mock:result"
+                    '''),
+                asResource('full-parameters-out-of-order)', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - saga:  
+                             propagation: "MANDATORY"
+                             completion-mode: "MANUAL"
+                             compensation: 
+                                 parameters:
+                                   name: compensation
+                                 uri: "direct"
+                             completion:
+                                 uri: "direct:completion"
+                             steps:
+                               - to: "direct:something"
+                             option:
+                               - option-name: o1
+                                 simple: "${body}" 
+                               - option-name: o2
+                                 expression:
+                                   simple: "${body}"        
+                          - to: "mock:result"
+                    '''),
                 asResource('short', '''
                     - from:
                         uri: "direct:start"
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ToDynamicTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ToDynamicTest.groovy
new file mode 100644
index 0000000..253b1c1
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ToDynamicTest.groovy
@@ -0,0 +1,126 @@
+/*
+ * 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.dsl.yaml.support.YamlTestSupport
+import org.apache.camel.model.ToDynamicDefinition
+import org.apache.camel.spi.Resource
+
+class ToDynamicTest extends YamlTestSupport {
+
+    def "to-d definition (#resource.location)"(Resource resource) {
+        when:
+            context.routesLoader.loadRoutes(resource)
+        then:
+            with(context.routeDefinitions[0].outputs[0], ToDynamicDefinition) {
+                uri == 'direct:start'
+            }
+        where:
+            resource << [
+                asResource('inline', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - to-d: "direct:start"
+                    '''),
+                asResource('uri', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - to-d: 
+                              uri: "direct:start"
+                    '''),
+                asResource('properties', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - to-d: 
+                              uri: "direct"
+                              parameters:
+                                name: "start"
+                    '''),
+                asResource('endpoint', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - to-d: 
+                              direct:
+                                name: "start"
+                    '''),
+                asResource('properties-out-of-order', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - to-d: 
+                              parameters:
+                                name: "start"
+                              uri: "direct"
+                    '''),
+            ]
+    }
+
+    def "to definition (#resource.location)"(Resource resource) {
+        when:
+            context.routesLoader.loadRoutes(resource)
+        then:
+            with(context.routeDefinitions[0].outputs[0], ToDynamicDefinition) {
+                uri == 'direct:start'
+            }
+        where:
+            resource << [
+                    asResource('inline', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - tod: "direct:start"
+                    '''),
+                    asResource('uri', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - tod: 
+                              uri: "direct:start"
+                    '''),
+                    asResource('properties', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - tod: 
+                              uri: "direct"
+                              parameters:
+                                name: "start"
+                    '''),
+                    asResource('endpoint', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - tod: 
+                              direct:
+                                name: "start"
+                    '''),
+                    asResource('properties-out-of-order', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - tod: 
+                              parameters:
+                                name: "start"
+                              uri: "direct"
+                    '''),
+            ]
+    }
+}
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ToTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ToTest.groovy
index 564a261..229d78e 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ToTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ToTest.groovy
@@ -67,7 +67,16 @@ class ToTest extends YamlTestSupport {
                         steps:    
                           - direct:
                               name: "start"
-                    ''')
+                    '''),
+                asResource('properties-out-of-order', '''
+                    - from:
+                        uri: "direct:start"
+                        steps:    
+                          - to: 
+                              parameters:
+                                name: "start"
+                              uri: "direct"
+                    '''),
             ]
     }
 }