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 2019/05/24 10:12:55 UTC

[camel] 15/27: CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.

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

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

commit 829296d324960c2ac58f3772046b8ede02ba959e
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu May 23 15:09:45 2019 +0200

    CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.
---
 .../camel/model/ProcessorDefinitionHelper.java     |   8 +-
 .../cloud/ServiceCallExpressionConfiguration.java  |   3 +-
 .../ServiceCallServiceChooserConfiguration.java    |   3 +-
 .../ServiceCallServiceDiscoveryConfiguration.java  |   3 +-
 .../ServiceCallServiceFilterConfiguration.java     |   3 +-
 ...erviceCallServiceLoadBalancerConfiguration.java |   3 +-
 .../management/JmxManagementStrategyFactory.java   |   3 +-
 .../DefaultComponentVerifierExtension.java         |  14 +-
 .../camel/support/PropertyBindingSupport.java      | 174 ++++++++++++++++-----
 .../camel/support/RestProducerFactoryHelper.java   |   7 +-
 .../camel/support/ScheduledPollConsumer.java       |  10 +-
 .../support/component/AbstractApiComponent.java    |   3 +-
 12 files changed, 163 insertions(+), 71 deletions(-)

diff --git a/core/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java b/core/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
index 35ebbb2..8852307 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
@@ -33,6 +33,7 @@ import org.apache.camel.NamedNode;
 import org.apache.camel.spi.ExecutorServiceManager;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.StringHelper;
 import org.slf4j.Logger;
@@ -644,9 +645,12 @@ public final class ProcessorDefinitionHelper {
             @Override
             public void run() {
                 try {
-                    IntrospectionSupport.setProperties(context, null, target, properties);
+                    // do not use property placeholders as we want to preserve the text as-is when we restore
+                    PropertyBindingSupport.build()
+                            .withPlaceholder(false).withNesting(false).withReference(false).withTarget(target).withProperties(properties)
+                            .bind(context);
                 } catch (Exception e) {
-                    LOG.warn("Could not restore definition properties", e);
+                    LOG.warn("Cannot restore definition properties. This exception is ignored.", e);
                 }
             }
         });
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java
index 32d203c..d9f753c 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java
@@ -43,6 +43,7 @@ import org.apache.camel.model.language.ExpressionDefinition;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 
 @Metadata(label = "routing,cloud")
 @XmlRootElement(name = "serviceExpression")
@@ -267,7 +268,7 @@ public class ServiceCallExpressionConfiguration extends IdentifiedType implement
 
                     postProcessFactoryParameters(camelContext, parameters);
 
-                    IntrospectionSupport.setProperties(factory, parameters);
+                    PropertyBindingSupport.bindProperties(camelContext, factory, parameters);
 
                     answer = factory.newInstance(camelContext);
                 } catch (Exception e) {
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java
index 313f15d..2dc6dfc 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java
@@ -39,6 +39,7 @@ import org.apache.camel.model.PropertyDefinition;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.util.ObjectHelper;
 
 @Metadata(label = "routing,cloud,service-discovery")
@@ -185,7 +186,7 @@ public class ServiceCallServiceChooserConfiguration extends IdentifiedType imple
 
                 postProcessFactoryParameters(camelContext, parameters);
 
-                IntrospectionSupport.setProperties(factory, parameters);
+                PropertyBindingSupport.bindProperties(camelContext, factory, parameters);
 
                 answer = factory.newInstance(camelContext);
             } catch (Exception e) {
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java
index 57c4ec4..d153f41 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java
@@ -40,6 +40,7 @@ import org.apache.camel.model.PropertyDefinition;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.util.ObjectHelper;
 
 @Metadata(label = "routing,cloud,service-discovery")
@@ -192,7 +193,7 @@ public class ServiceCallServiceDiscoveryConfiguration extends IdentifiedType imp
 
                 postProcessFactoryParameters(camelContext, parameters);
 
-                IntrospectionSupport.setProperties(factory, parameters);
+                PropertyBindingSupport.bindProperties(camelContext, factory, parameters);
 
                 answer = factory.newInstance(camelContext);
             } catch (Exception e) {
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java
index a0465a3..db7887e 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java
@@ -39,6 +39,7 @@ import org.apache.camel.model.PropertyDefinition;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.util.ObjectHelper;
 
 @Metadata(label = "routing,cloud,service-discovery")
@@ -185,7 +186,7 @@ public class ServiceCallServiceFilterConfiguration extends IdentifiedType implem
 
                 postProcessFactoryParameters(camelContext, parameters);
 
-                IntrospectionSupport.setProperties(factory, parameters);
+                PropertyBindingSupport.bindProperties(camelContext, factory, parameters);
 
                 answer = factory.newInstance(camelContext);
             } catch (Exception e) {
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceLoadBalancerConfiguration.java b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceLoadBalancerConfiguration.java
index 6e42e34e..6794a23 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceLoadBalancerConfiguration.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceLoadBalancerConfiguration.java
@@ -39,6 +39,7 @@ import org.apache.camel.model.PropertyDefinition;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.util.ObjectHelper;
 
 @Metadata(label = "routing,cloud,load-balancing")
@@ -185,7 +186,7 @@ public class ServiceCallServiceLoadBalancerConfiguration extends IdentifiedType
 
                 postProcessFactoryParameters(camelContext, parameters);
 
-                IntrospectionSupport.setProperties(factory, parameters);
+                PropertyBindingSupport.bindProperties(camelContext, factory, parameters);
 
                 answer = factory.newInstance(camelContext);
             } catch (Exception e) {
diff --git a/core/camel-management-impl/src/main/java/org/apache/camel/management/JmxManagementStrategyFactory.java b/core/camel-management-impl/src/main/java/org/apache/camel/management/JmxManagementStrategyFactory.java
index 6afcb47..b0dfde0 100644
--- a/core/camel-management-impl/src/main/java/org/apache/camel/management/JmxManagementStrategyFactory.java
+++ b/core/camel-management-impl/src/main/java/org/apache/camel/management/JmxManagementStrategyFactory.java
@@ -23,6 +23,7 @@ import org.apache.camel.spi.LifecycleStrategy;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.spi.ManagementStrategyFactory;
 import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 
 /**
  * Factory for creating JMX {@link ManagementStrategy}.
@@ -32,7 +33,7 @@ public class JmxManagementStrategyFactory implements ManagementStrategyFactory {
     public ManagementStrategy create(CamelContext context, Map<String, Object> options) throws Exception {
         DefaultManagementAgent agent = new DefaultManagementAgent(context);
         if (options != null) {
-            IntrospectionSupport.setProperties(agent, options);
+            PropertyBindingSupport.bindProperties(context, agent, options);
         }
 
         return new JmxManagementStrategy(context, agent);
diff --git a/core/camel-support/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java b/core/camel-support/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java
index e8b27f1..9e751de 100644
--- a/core/camel-support/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java
+++ b/core/camel-support/src/main/java/org/apache/camel/component/extension/verifier/DefaultComponentVerifierExtension.java
@@ -32,6 +32,7 @@ import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.EndpointHelper;
 import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 
 import static org.apache.camel.util.StreamUtils.stream;
 
@@ -188,18 +189,7 @@ public class DefaultComponentVerifierExtension implements ComponentVerifierExten
         }
 
         if (!properties.isEmpty()) {
-            final TypeConverter converter = camelContext.getTypeConverter();
-
-            IntrospectionSupport.setProperties(converter, instance, properties);
-
-            for (Map.Entry<String, Object> entry : properties.entrySet()) {
-                if (entry.getValue() instanceof String) {
-                    String value = (String)entry.getValue();
-                    if (EndpointHelper.isReferenceParameter(value)) {
-                        IntrospectionSupport.setProperty(camelContext, converter, instance, entry.getKey(), null, value, true);
-                    }
-                }
-            }
+            PropertyBindingSupport.bindProperties(camelContext, instance, properties);
         }
 
         return instance;
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
index 02c24c1..99f9638 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
@@ -43,11 +43,65 @@ import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
  */
 public final class PropertyBindingSupport {
 
+    public static class Builder {
+
+        private boolean nesting = true;
+        private boolean reference = true;
+        private boolean placeholder = true;
+        private boolean fluentBuilder = true;
+
+        private Object target;
+        private Map<String, Object> properties;
+
+        public Builder withNesting(boolean nesting) {
+            this.nesting = nesting;
+            return this;
+        }
+
+        public Builder withReference(boolean reference) {
+            this.reference = reference;
+            return this;
+        }
+
+        public Builder withPlaceholder(boolean placeholder) {
+            this.placeholder = placeholder;
+            return this;
+        }
+
+        public Builder withFluentBuilder(boolean fluentBuilder) {
+            this.fluentBuilder = fluentBuilder;
+            return this;
+        }
+
+        public Builder withTarget(Object target) {
+            this.target = target;
+            return this;
+        }
+
+        public Builder withProperties(Map<String, Object> properties) {
+            this.properties = properties;
+            return this;
+        }
+
+        public boolean bind(CamelContext camelContext) {
+            org.apache.camel.util.ObjectHelper.notNull(camelContext, "camelContext");
+            org.apache.camel.util.ObjectHelper.notNull(target, "target");
+            org.apache.camel.util.ObjectHelper.notNull(properties, "properties");
+
+            return bindProperties(camelContext, target, properties, nesting, fluentBuilder, reference, placeholder);
+        }
+
+    }
+
     // TODO: Add support for Map/List
 
     private PropertyBindingSupport() {
     }
 
+    public static Builder build() {
+        return new Builder();
+    }
+
     @FunctionalInterface
     public interface OnAutowiring {
 
@@ -141,20 +195,38 @@ public final class PropertyBindingSupport {
      * @return              true if one or more properties was bound
      */
     public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties) {
+        return bindProperties(camelContext, target, properties, true, true, true, true);
+   }
+
+    /**
+     * Binds the properties to the target object, and removes the property that was bound from properties.
+     *
+     * @param camelContext  the camel context
+     * @param target        the target object
+     * @param properties    the properties where the bound properties will be removed from
+     * @param nesting       whether nesting is in use
+     * @param fluentBuilder whether fluent builder is allowed as a valid getter/setter
+     * @param reference     whether reference parameter (syntax starts with #) is in use
+     * @param placeholder   whether to use Camels property placeholder to resolve placeholders on keys and values
+     * @return              true if one or more properties was bound
+     */
+    public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties,
+                                         boolean nesting, boolean fluentBuilder, boolean reference, boolean placeholder) {
+        org.apache.camel.util.ObjectHelper.notNull(camelContext, "camelContext");
         org.apache.camel.util.ObjectHelper.notNull(target, "target");
         org.apache.camel.util.ObjectHelper.notNull(properties, "properties");
         boolean rc = false;
 
         for (Iterator<Map.Entry<String, Object>> iter = properties.entrySet().iterator(); iter.hasNext();) {
             Map.Entry<String, Object> entry = iter.next();
-            if (bindProperty(camelContext, target, entry.getKey(), entry.getValue())) {
+            if (bindProperty(camelContext, target, entry.getKey(), entry.getValue(), nesting, fluentBuilder, reference, placeholder)) {
                 iter.remove();
                 rc = true;
             }
         }
 
         return rc;
-   }
+    }
 
     /**
      * Binds the property to the target object.
@@ -168,7 +240,20 @@ public final class PropertyBindingSupport {
     public static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value) {
         try {
             if (target != null && name != null) {
-                return setProperty(camelContext, target, name, value);
+                return setProperty(camelContext, target, name, value, true, true, true, true);
+            }
+        } catch (Exception e) {
+            throw new PropertyBindingException(target, name, e);
+        }
+
+        return false;
+    }
+
+    private static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value,
+                                boolean nesting, boolean fluentBuilder, boolean reference, boolean placeholder) {
+        try {
+            if (target != null && name != null) {
+                return setProperty(camelContext, target, name, value, nesting, fluentBuilder, reference, placeholder);
             }
         } catch (Exception e) {
             throw new PropertyBindingException(target, name, e);
@@ -188,7 +273,7 @@ public final class PropertyBindingSupport {
     public static void bindMandatoryProperty(CamelContext camelContext, Object target, String name, Object value) {
         try {
             if (target != null && name != null) {
-                boolean bound = setProperty(camelContext, target, name, value);
+                boolean bound = setProperty(camelContext, target, name, value, true, true, true, true);
                 if (!bound) {
                     throw new PropertyBindingException(target, name);
                 }
@@ -198,50 +283,55 @@ public final class PropertyBindingSupport {
         }
     }
 
-    private static boolean setProperty(CamelContext context, Object target, String name, Object value) throws Exception {
+    private static boolean setProperty(CamelContext context, Object target, String name, Object value,
+                                       boolean nesting, boolean fluentBuilder, boolean reference, boolean placeholder) throws Exception {
         String refName = null;
 
-        // resolve property placeholders
-        name = context.resolvePropertyPlaceholders(name);
-        if (value instanceof String) {
+        if (placeholder) {
             // resolve property placeholders
-            value = context.resolvePropertyPlaceholders(value.toString());
+            name = context.resolvePropertyPlaceholders(name);
+            if (value instanceof String) {
+                // resolve property placeholders
+                value = context.resolvePropertyPlaceholders(value.toString());
+            }
         }
 
         // if name has dot then we need to OGNL walk it
-        if (name.indexOf('.') > 0) {
-            String[] parts = name.split("\\.");
-            Object newTarget = target;
-            Class<?> newClass = target.getClass();
-            // we should only iterate until until 2nd last so we use -1 in the for loop
-            for (int i = 0; i < parts.length - 1; i++) {
-                String part = parts[i];
-                Object prop = getOrElseProperty(newTarget, part, null);
-                if (prop == null) {
-                    // okay is there a setter so we can create a new instance and set it automatic
-                    Method method = findBestSetterMethod(newClass, part);
-                    if (method != null) {
-                        Class<?> parameterType = method.getParameterTypes()[0];
-                        if (parameterType != null && org.apache.camel.util.ObjectHelper.hasDefaultPublicNoArgConstructor(parameterType)) {
-                            Object instance = context.getInjector().newInstance(parameterType);
-                            if (instance != null) {
-                                org.apache.camel.support.ObjectHelper.invokeMethod(method, newTarget, instance);
-                                newTarget = instance;
-                                newClass = newTarget.getClass();
+        if (nesting) {
+            if (name.indexOf('.') > 0) {
+                String[] parts = name.split("\\.");
+                Object newTarget = target;
+                Class<?> newClass = target.getClass();
+                // we should only iterate until until 2nd last so we use -1 in the for loop
+                for (int i = 0; i < parts.length - 1; i++) {
+                    String part = parts[i];
+                    Object prop = getOrElseProperty(newTarget, part, null);
+                    if (prop == null) {
+                        // okay is there a setter so we can create a new instance and set it automatic
+                        Method method = findBestSetterMethod(newClass, part, fluentBuilder);
+                        if (method != null) {
+                            Class<?> parameterType = method.getParameterTypes()[0];
+                            if (parameterType != null && org.apache.camel.util.ObjectHelper.hasDefaultPublicNoArgConstructor(parameterType)) {
+                                Object instance = context.getInjector().newInstance(parameterType);
+                                if (instance != null) {
+                                    org.apache.camel.support.ObjectHelper.invokeMethod(method, newTarget, instance);
+                                    newTarget = instance;
+                                    newClass = newTarget.getClass();
+                                }
                             }
                         }
+                    } else {
+                        newTarget = prop;
+                        newClass = newTarget.getClass();
                     }
-                } else {
-                    newTarget = prop;
-                    newClass = newTarget.getClass();
                 }
+                // okay we found a nested property, then lets change to use that
+                target = newTarget;
+                name = parts[parts.length - 1];
             }
-            // okay we found a nested property, then lets change to use that
-            target = newTarget;
-            name = parts[parts.length - 1];
         }
 
-        if (value instanceof String) {
+        if (reference && value instanceof String) {
             if (value.toString().startsWith("#class:")) {
                 // its a new class to be created
                 String className = value.toString().substring(6);
@@ -261,7 +351,7 @@ public final class PropertyBindingSupport {
                 }
             } else if (value.toString().equals("#autowire")) {
                 // we should get the type from the setter
-                Method method = findBestSetterMethod(target.getClass(), name);
+                Method method = findBestSetterMethod(target.getClass(), name, fluentBuilder);
                 if (method != null) {
                     Class<?> parameterType = method.getParameterTypes()[0];
                     if (parameterType != null) {
@@ -282,10 +372,10 @@ public final class PropertyBindingSupport {
             }
         }
 
-        return IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, true);
+        return IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, fluentBuilder);
     }
 
-    private static Method findBestSetterMethod(Class clazz, String name) {
+    private static Method findBestSetterMethod(Class clazz, String name, boolean fluentBuilder) {
         // is there a direct setter?
         Set<Method> candidates = findSetterMethods(clazz, name, false);
         if (candidates.size() == 1) {
@@ -293,9 +383,11 @@ public final class PropertyBindingSupport {
         }
 
         // okay now try with builder pattern
-        candidates = findSetterMethods(clazz, name, true);
-        if (candidates.size() == 1) {
-            return candidates.iterator().next();
+        if (fluentBuilder) {
+            candidates = findSetterMethods(clazz, name, true);
+            if (candidates.size() == 1) {
+                return candidates.iterator().next();
+            }
         }
 
         return null;
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/RestProducerFactoryHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/RestProducerFactoryHelper.java
index 657a33d..743f551 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/RestProducerFactoryHelper.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/RestProducerFactoryHelper.java
@@ -16,7 +16,7 @@
  */
 package org.apache.camel.support;
 
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
@@ -74,9 +74,8 @@ public final class RestProducerFactoryHelper {
         // need to make a copy of the component properties as
         // IntrospectionSupport::setProperties will remove any that are set and
         // we might be called multiple times
-        final Map<String, Object> copyOfComponentProperties = new HashMap<>(componentProperties);
-        IntrospectionSupport.setProperties(camelContext, camelContext.getTypeConverter(), newlyCreated,
-            copyOfComponentProperties);
+        final Map<String, Object> copyOfComponentProperties = new LinkedHashMap<>(componentProperties);
+        PropertyBindingSupport.bindProperties(camelContext, newlyCreated, copyOfComponentProperties);
         ServiceHelper.startService(newlyCreated);
 
         return newlyCreated;
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollConsumer.java b/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollConsumer.java
index 2bc5e2f..1244fe5 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollConsumer.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollConsumer.java
@@ -16,7 +16,7 @@
  */
 package org.apache.camel.support;
 
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -417,13 +417,13 @@ public abstract class ScheduledPollConsumer extends DefaultConsumer implements R
         scheduler.onInit(this);
 
         // configure scheduler with options from this consumer
-        Map<String, Object> properties = new HashMap<>();
+        Map<String, Object> properties = new LinkedHashMap<>();
         IntrospectionSupport.getProperties(this, properties, null);
-        IntrospectionSupport.setProperties(getEndpoint().getCamelContext().getTypeConverter(), scheduler, properties);
+        PropertyBindingSupport.bindProperties(getEndpoint().getCamelContext(), scheduler, properties);
         if (schedulerProperties != null && !schedulerProperties.isEmpty()) {
             // need to use a copy in case the consumer is restarted so we keep the properties
-            Map<String, Object> copy = new HashMap<>(schedulerProperties);
-            IntrospectionSupport.setProperties(getEndpoint().getCamelContext().getTypeConverter(), scheduler, copy);
+            Map<String, Object> copy = new LinkedHashMap<>(schedulerProperties);
+            PropertyBindingSupport.bindProperties(getEndpoint().getCamelContext(), scheduler, copy);
             if (copy.size() > 0) {
                 throw new FailedToCreateConsumerException(getEndpoint(), "There are " + copy.size()
                         + " scheduler parameters that couldn't be set on the endpoint."
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/component/AbstractApiComponent.java b/core/camel-support/src/main/java/org/apache/camel/support/component/AbstractApiComponent.java
index d4cea3e..808c4ef 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/component/AbstractApiComponent.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/component/AbstractApiComponent.java
@@ -26,6 +26,7 @@ import org.apache.camel.Endpoint;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.support.DefaultComponent;
 import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.support.PropertyBindingSupport;
 
 /**
  * Abstract base class for API Component Camel {@link org.apache.camel.Component} classes.
@@ -111,7 +112,7 @@ public abstract class AbstractApiComponent<E extends Enum<E> & ApiName, T, S ext
 
         // create endpoint configuration with component properties
         final T endpointConfiguration = collection.getEndpointConfiguration(name);
-        IntrospectionSupport.setProperties(endpointConfiguration, componentProperties);
+        PropertyBindingSupport.bindProperties(getCamelContext(), endpointConfiguration, componentProperties);
         return endpointConfiguration;
     }