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 06:24:56 UTC

[camel] branch 13557 updated (d008968 -> 16cc010)

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

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


    from d008968  CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.
     new 32d5033  CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.
     new 16cc010  CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../org/apache/camel/support/DefaultComponent.java | 45 ++++++++++++++---
 .../org/apache/camel/support/DefaultEndpoint.java  | 40 ++++++++++++---
 .../org/apache/camel/support/EndpointHelper.java   |  6 ++-
 .../camel/support/PropertyBindingSupport.java      | 57 +++++++++++++++++-----
 .../camel/support/ScheduledPollEndpoint.java       |  5 +-
 .../support/component/AbstractApiEndpoint.java     |  3 +-
 6 files changed, 126 insertions(+), 30 deletions(-)


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

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 16cc010f8c964ff022dc0a0d03a002c901fcdab0
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri May 24 08:22:38 2019 +0200

    CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.
---
 .../org/apache/camel/support/DefaultComponent.java | 45 +++++++++++++++++++---
 .../org/apache/camel/support/DefaultEndpoint.java  | 40 +++++++++++++++----
 .../org/apache/camel/support/EndpointHelper.java   |  6 ++-
 .../camel/support/ScheduledPollEndpoint.java       |  5 +--
 .../support/component/AbstractApiEndpoint.java     |  3 +-
 5 files changed, 80 insertions(+), 19 deletions(-)

diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java
index 9922aea..ba16cf3 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultComponent.java
@@ -40,7 +40,6 @@ import org.apache.camel.util.URISupport;
 import org.apache.camel.util.UnsafeUriCharactersEncoder;
 import org.apache.camel.util.function.Suppliers;
 
-
 /**
  * Default component to use for base for components implementations.
  */
@@ -58,6 +57,9 @@ public abstract class DefaultComponent extends ServiceSupport implements Compone
     @Metadata(label = "advanced", defaultValue = "true",
         description = "Whether the component should resolve property placeholders on itself when starting. Only properties which are of String type can use property placeholders.")
     private boolean resolvePropertyPlaceholders = true;
+    @Metadata(label = "advanced",
+        description = "Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities")
+    private boolean basicPropertyBinding;
 
     public DefaultComponent() {
     }
@@ -124,6 +126,12 @@ public abstract class DefaultComponent extends ServiceSupport implements Compone
             return null;
         }
 
+        // setup whether to use basic property binding or not which must be done before we set properties 
+        boolean basic = getAndRemoveParameter(parameters, "basicPropertyBinding", boolean.class, basicPropertyBinding);
+        if (endpoint instanceof DefaultEndpoint) {
+            ((DefaultEndpoint) endpoint).setBasicPropertyBinding(basic);
+        }
+
         endpoint.configureProperties(parameters);
         if (useIntrospectionOnEndpoint()) {
             setProperties(endpoint, parameters);
@@ -162,6 +170,20 @@ public abstract class DefaultComponent extends ServiceSupport implements Compone
     }
 
     /**
+     * Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities.
+     */
+    public boolean isBasicPropertyBinding() {
+        return basicPropertyBinding;
+    }
+
+    /**
+     * Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities.
+     */
+    public void setBasicPropertyBinding(boolean basicPropertyBinding) {
+        this.basicPropertyBinding = basicPropertyBinding;
+    }
+
+    /**
      * Strategy to do post configuration logic.
      * <p/>
      * Can be used to construct an URI based on the remaining parameters. For example the parameters that configures
@@ -274,7 +296,7 @@ public abstract class DefaultComponent extends ServiceSupport implements Compone
     /**
      * Sets the bean properties on the given bean
      *
-     * @param bean  the bean
+     * @param bean        the bean
      * @param parameters  properties to set
      */
     protected void setProperties(Object bean, Map<String, Object> parameters) throws Exception {
@@ -282,15 +304,26 @@ public abstract class DefaultComponent extends ServiceSupport implements Compone
     }
 
     /**
-     * Sets the bean properties on the given bean using the given {@link CamelContext}
+     * Sets the bean properties on the given bean using the given {@link CamelContext}.
+     *
      * @param camelContext  the {@link CamelContext} to use
-     * @param bean  the bean
-     * @param parameters  properties to set
+     * @param bean          the bean
+     * @param parameters    properties to set
      */
     protected void setProperties(CamelContext camelContext, Object bean, Map<String, Object> parameters) throws Exception {
         // set reference properties first as they use # syntax that fools the regular properties setter
+        // TODO: We should find out the weird camel-cxf error where we need to do this, as we can put this logic into PropertyBindingSupport
         EndpointHelper.setReferenceProperties(camelContext, bean, parameters);
-        EndpointHelper.setProperties(camelContext, bean, parameters);
+
+        if (basicPropertyBinding) {
+            // use basic binding
+            PropertyBindingSupport.build()
+                    .withPlaceholder(false).withNesting(false).withNestingDeep(false).withReference(false)
+                    .bind(camelContext, bean, parameters);
+        } else {
+            // use advanced binding
+            PropertyBindingSupport.bindProperties(camelContext, bean, parameters);
+        }
     }
 
     /**
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultEndpoint.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultEndpoint.java
index 42e6182..801f18c 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultEndpoint.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultEndpoint.java
@@ -31,6 +31,7 @@ import org.apache.camel.PollingConsumer;
 import org.apache.camel.ResolveEndpointFailedException;
 import org.apache.camel.spi.ExceptionHandler;
 import org.apache.camel.spi.HasId;
+import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.UriParam;
 import org.apache.camel.support.service.ServiceSupport;
 import org.apache.camel.util.ObjectHelper;
@@ -72,6 +73,9 @@ public abstract class DefaultEndpoint extends ServiceSupport implements Endpoint
     @UriParam(defaultValue = "false", label = "advanced",
             description = "Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported).")
     private boolean synchronous;
+    @UriParam(label = "advanced",
+            description = "Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities")
+    private boolean basicPropertyBinding;
     // these options are not really in use any option related to the consumer has a specific option on the endpoint
     // and consumerProperties was added from the very start of Camel.
     private Map<String, Object> consumerProperties;
@@ -247,6 +251,20 @@ public abstract class DefaultEndpoint extends ServiceSupport implements Endpoint
         this.synchronous = synchronous;
     }
 
+    /**
+     * Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities.
+     */
+    public boolean isBasicPropertyBinding() {
+        return basicPropertyBinding;
+    }
+
+    /**
+     * Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities.
+     */
+    public void setBasicPropertyBinding(boolean basicPropertyBinding) {
+        this.basicPropertyBinding = basicPropertyBinding;
+    }
+
     public boolean isBridgeErrorHandler() {
         return bridgeErrorHandler;
     }
@@ -358,13 +376,22 @@ public abstract class DefaultEndpoint extends ServiceSupport implements Endpoint
      * <p/>
      * This is the same logical implementation as {@link DefaultComponent#setProperties(Object, java.util.Map)}
      *
-     * @param bean  the bean
+     * @param bean        the bean
      * @param parameters  properties to set
      */
     protected void setProperties(Object bean, Map<String, Object> parameters) throws Exception {
         // set reference properties first as they use # syntax that fools the regular properties setter
-        EndpointHelper.setReferenceProperties(getCamelContext(), bean, parameters);
-        EndpointHelper.setProperties(getCamelContext(), bean, parameters);
+        EndpointHelper.setReferenceProperties(camelContext, bean, parameters);
+
+        if (basicPropertyBinding) {
+            // use basic binding
+            PropertyBindingSupport.build()
+                    .withPlaceholder(false).withNesting(false).withNestingDeep(false).withReference(false)
+                    .bind(camelContext, bean, parameters);
+        } else {
+            // use advanced binding
+            PropertyBindingSupport.bindProperties(camelContext, bean, parameters);
+        }
     }
 
     /**
@@ -439,13 +466,12 @@ public abstract class DefaultEndpoint extends ServiceSupport implements Endpoint
             // and in case we restart routes, we need access to the original consumer properties again
             Map<String, Object> copy = new HashMap<>(consumerProperties);
 
-            // set reference properties first as they use # syntax that fools the regular properties setter
-            EndpointHelper.setReferenceProperties(getCamelContext(), consumer, copy);
-            EndpointHelper.setProperties(getCamelContext(), consumer, copy);
+            // configure consumer
+            setProperties(consumer, copy);
 
             // special consumer.bridgeErrorHandler option
             Object bridge = copy.remove("bridgeErrorHandler");
-            if (bridge != null && "true".equals(bridge)) {
+            if ("true".equals(bridge)) {
                 if (consumer instanceof DefaultConsumer) {
                     DefaultConsumer defaultConsumer = (DefaultConsumer) consumer;
                     defaultConsumer.setExceptionHandler(new BridgeExceptionHandlerToErrorHandler(defaultConsumer));
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
index 0dd2adc..c19c240 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
@@ -155,7 +155,9 @@ public final class EndpointHelper {
      * @param bean       the bean
      * @param parameters parameters
      * @throws Exception is thrown if setting property fails
+     * @deprecated use PropertyBindingSupport
      */
+    @Deprecated
     public static void setProperties(CamelContext context, Object bean, Map<String, Object> parameters) throws Exception {
         // use the property binding which can do more advanced configuration
         PropertyBindingSupport.bindProperties(context, bean, parameters);
@@ -171,7 +173,9 @@ public final class EndpointHelper {
      * @param bean       the bean
      * @param parameters parameters
      * @throws Exception is thrown if setting property fails
+     * @deprecated use PropertyBindingSupport
      */
+    @Deprecated
     public static void setReferenceProperties(CamelContext context, Object bean, Map<String, Object> parameters) throws Exception {
         Iterator<Map.Entry<String, Object>> it = parameters.entrySet().iterator();
         while (it.hasNext()) {
@@ -179,7 +183,7 @@ public final class EndpointHelper {
             String name = entry.getKey();
             Object v = entry.getValue();
             String value = v != null ? v.toString() : null;
-            if (value != null && isReferenceParameter(value)) {
+            if (isReferenceParameter(value)) {
                 boolean hit = IntrospectionSupport.setProperty(context, context.getTypeConverter(), bean, name, null, value, true);
                 if (hit) {
                     // must remove as its a valid option and we could configure it
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollEndpoint.java b/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollEndpoint.java
index 861b3b8..067be27 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollEndpoint.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollEndpoint.java
@@ -146,9 +146,8 @@ public abstract class ScheduledPollEndpoint extends DefaultEndpoint {
         // as these options are not supported on the polling consumer
         configureScheduledPollConsumerProperties(copy, throwaway);
 
-        // set reference properties first as they use # syntax that fools the regular properties setter
-        EndpointHelper.setReferenceProperties(getCamelContext(), consumer, copy);
-        EndpointHelper.setProperties(getCamelContext(), consumer, copy);
+        // configure consumer
+        setProperties(consumer, copy);
 
         if (!isLenientProperties() && copy.size() > 0) {
             throw new ResolveEndpointFailedException(this.getEndpointUri(), "There are " + copy.size()
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/component/AbstractApiEndpoint.java b/core/camel-support/src/main/java/org/apache/camel/support/component/AbstractApiEndpoint.java
index 1f47392..6391898 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/component/AbstractApiEndpoint.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/component/AbstractApiEndpoint.java
@@ -102,8 +102,7 @@ public abstract class AbstractApiEndpoint<E extends ApiName, T>
         // set configuration properties first
         try {
             T configuration = getConfiguration();
-            EndpointHelper.setReferenceProperties(getCamelContext(), configuration, options);
-            EndpointHelper.setProperties(getCamelContext(), configuration, options);
+            setProperties(configuration, options);
         } catch (Exception e) {
             throw new IllegalArgumentException(e);
         }


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

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 32d50330351818d13e3fe5cfc0fdae9fc134a6c4
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri May 24 08:00:40 2019 +0200

    CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.
---
 .../camel/support/PropertyBindingSupport.java      | 57 +++++++++++++++++-----
 1 file changed, 46 insertions(+), 11 deletions(-)

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 14e6a37..79916c9 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
@@ -37,14 +37,13 @@ import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
  *     <li>reference by bean id - Values can refer to other beans in the registry by prefixing with #nean: eg #bean:myBean</li>
  *     <li>reference by type - Values can refer to singleton beans by their type in the registry by prefixing with #type: syntax, eg #type:com.foo.MyClassType</li>
  *     <li>autowire by type - Values can refer to singleton beans by auto wiring by setting the value to #autowire</li>
- *     <li>new class - Values can refer to creating new beans by their class name syntax, eg class:com.foo.MyClassType</li>
+ *     <li>reference new class - Values can refer to creating new beans by their class name by prefixing with #class, eg #class:com.foo.MyClassType</li>
  * </ul>
  * This implementations reuses parts of {@link IntrospectionSupport}.
  */
 public final class PropertyBindingSupport {
 
     // TODO: Add support for Map/List
-    // TODO: Add option to turn on|off new class
     // TODO: Add option to turn this binding on|off on component/endpoint level
 
     /**
@@ -53,36 +52,66 @@ public final class PropertyBindingSupport {
     public static class Builder {
 
         private boolean nesting = true;
+        private boolean nestingDeep = true;
         private boolean reference = true;
         private boolean placeholder = true;
         private boolean fluentBuilder = true;
 
+        /**
+         * Whether nesting is in use
+         */
         public Builder withNesting(boolean nesting) {
             this.nesting = nesting;
             return this;
         }
 
+        /**
+         * Whether deep nesting is in use, where Camel will attempt to walk as deep as possible by creating new objects in the OGNL graph if
+         * a property has a setter and the object can be created from a default no-arg constructor.
+         */
+        public Builder withNestingDeep(boolean nestingDeep) {
+            this.nestingDeep = nestingDeep;
+            return this;
+        }
+
+        /**
+         * Whether reference parameter (syntax starts with #) is in use
+         */
         public Builder withReference(boolean reference) {
             this.reference = reference;
             return this;
         }
 
+        /**
+         * Whether to use Camels property placeholder to resolve placeholders on keys and values
+         */
         public Builder withPlaceholder(boolean placeholder) {
             this.placeholder = placeholder;
             return this;
         }
 
+        /**
+         * Whether fluent builder is allowed as a valid getter/setter
+         */
         public Builder withFluentBuilder(boolean fluentBuilder) {
             this.fluentBuilder = fluentBuilder;
             return this;
         }
 
+        /**
+         * 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
+         * @return              true if one or more properties was bound
+         */
         public boolean bind(CamelContext camelContext, Object target, Map<String, Object> properties) {
             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);
+            return bindProperties(camelContext, target, properties, nesting, nestingDeep, fluentBuilder, reference, placeholder);
         }
 
     }
@@ -189,7 +218,7 @@ 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);
+        return bindProperties(camelContext, target, properties, true, true, true, true, true);
    }
 
     /**
@@ -199,13 +228,15 @@ public final class PropertyBindingSupport {
      * @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 nestingDeep   whether deep nesting is in use, where Camel will attempt to walk as deep as possible by creating new objects in the OGNL graph if
+     *                      a property has a setter and the object can be created from a default no-arg constructor.
      * @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) {
+                                         boolean nesting, boolean nestingDeep, 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");
@@ -213,7 +244,7 @@ public final class PropertyBindingSupport {
 
         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(), nesting, fluentBuilder, reference, placeholder)) {
+            if (bindProperty(camelContext, target, entry.getKey(), entry.getValue(), nesting, nestingDeep, fluentBuilder, reference, placeholder)) {
                 iter.remove();
                 rc = true;
             }
@@ -234,7 +265,7 @@ 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, true, true, true, true);
+                return setProperty(camelContext, target, name, value, true, true, true, true, true);
             }
         } catch (Exception e) {
             throw new PropertyBindingException(target, name, e);
@@ -244,10 +275,10 @@ public final class PropertyBindingSupport {
     }
 
     private static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value,
-                                boolean nesting, boolean fluentBuilder, boolean reference, boolean placeholder) {
+                                boolean nesting, boolean nestingDeep, boolean fluentBuilder, boolean reference, boolean placeholder) {
         try {
             if (target != null && name != null) {
-                return setProperty(camelContext, target, name, value, nesting, fluentBuilder, reference, placeholder);
+                return setProperty(camelContext, target, name, value, nesting, nestingDeep, fluentBuilder, reference, placeholder);
             }
         } catch (Exception e) {
             throw new PropertyBindingException(target, name, e);
@@ -267,7 +298,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, true, true, true, true);
+                boolean bound = setProperty(camelContext, target, name, value, true, true, true, true, true);
                 if (!bound) {
                     throw new PropertyBindingException(target, name);
                 }
@@ -278,7 +309,7 @@ public final class PropertyBindingSupport {
     }
 
     private static boolean setProperty(CamelContext context, Object target, String name, Object value,
-                                       boolean nesting, boolean fluentBuilder, boolean reference, boolean placeholder) throws Exception {
+                                       boolean nesting, boolean nestingDeep, boolean fluentBuilder, boolean reference, boolean placeholder) throws Exception {
         String refName = null;
 
         if (placeholder) {
@@ -301,6 +332,10 @@ public final class PropertyBindingSupport {
                     String part = parts[i];
                     Object prop = getOrElseProperty(newTarget, part, null);
                     if (prop == null) {
+                        if (!nestingDeep) {
+                            // okay we cannot go further down
+                            break;
+                        }
                         // 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) {