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 126bdac5d7dcde4d55a0f6079b8794cc4a47e6ef
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Jun 3 20:06:04 2019 +0200

    camel-spring-boot should use PropertyBindingSupport when setting properties 
on components etc via the helper class.
---
 .../spring/boot/util/CamelPropertiesHelper.java    | 48 +++++++-----
 .../boot/util/CamelPropertiesHelperTest.java       | 87 +++++++++++++++++++++-
 .../apache/camel/spring/boot/util/MyFooClass.java  | 46 ++++++++++++
 3 files changed, 159 insertions(+), 22 deletions(-)

diff --git 
a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/util/CamelPropertiesHelper.java
 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/util/CamelPropertiesHelper.java
index e5627db..a6a415f 100644
--- 
a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/util/CamelPropertiesHelper.java
+++ 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/util/CamelPropertiesHelper.java
@@ -20,11 +20,10 @@ import java.util.Iterator;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.support.IntrospectionSupport;
+import org.apache.camel.PropertyBindingException;
+import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.util.ObjectHelper;
 
-import static org.apache.camel.support.EndpointHelper.isReferenceParameter;
-
 /**
  * To help configuring Camel properties that have been defined in Spring Boot 
configuration files.
  */
@@ -36,11 +35,21 @@ public final class CamelPropertiesHelper {
     /**
      * Sets the properties on the target bean.
      * <p/>
-     * This implementation sets the properties using the following algorithm:
+     * This method uses {@link PropertyBindingSupport} and therefore offers 
its capabilities such as:
+     * <ul>
+     *     <li>property placeholders - Keys and values using Camels property 
placeholder will be resolved</li>
+     *     <li>nested - Properties can be nested using the dot syntax (OGNL 
and builder pattern using with as prefix), eg foo.bar=123</li>
+     *     <li>map</li> - Properties can lookup in Map's using map syntax, eg 
foo[bar] where foo is the name of the property that is a Map instance, and bar 
is the name of the key.</li>
+     *     <li>list</li> - Properties can refer or add to in List's using list 
syntax, eg foo[0] where foo is the name of the property that is a
+     *                     List instance, and 0 is the index. To refer to the 
last element, then use last as key.</li>
+     * </ul>
+     * This implementation sets the properties using the following algorithm 
in the given order:
      * <ul>
-     *     <li>Value as reference lookup - If the value uses Camel reference 
syntax, eg #beanId then the bean is looked up from Registry and set on the 
target</li>
-     *     <li>Value as-is - The value is attempted to be converted to the 
class type of the bean setter method; this is for regular types like String, 
numbers etc</li>
-     *     <li>Value as lookup - the bean is looked up from Registry and if 
there is a bean then its set on the target</li>
+     *     <li>reference by bean id - Values can refer to other beans in the 
registry by prefixing with with # or #bean: eg #myBean or #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 #autowired</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>
+     *     <li>value as lookup - The value is used as-is (eg like #value) to 
lookup in the Registry if there is a bean then its set on the target</li>
      * </ul>
      * When an option has been set on the target bean, then its removed from 
the given properties map. If all the options has been set, then the map will be 
empty.
      *
@@ -58,8 +67,6 @@ public final class CamelPropertiesHelper {
         ObjectHelper.notNull(properties, "properties");
         boolean rc = false;
 
-        // TODO: Use BindingPropertySupport instead of IntrospectionSupport
-
         Iterator<Map.Entry<String, Object>> it = 
properties.entrySet().iterator();
         while (it.hasNext()) {
             Map.Entry<String, Object> entry = it.next();
@@ -67,17 +74,18 @@ public final class CamelPropertiesHelper {
             Object value = entry.getValue();
             String stringValue = value != null ? value.toString() : null;
             boolean hit = false;
-            if (stringValue != null && isReferenceParameter(stringValue)) {
-                // its a #beanId reference lookup
-                hit = IntrospectionSupport.setProperty(context, 
context.getTypeConverter(), target, name, null, stringValue, true);
-            } else if (value != null) {
-                // its a value to be used as-is (or type converted)
-                try {
-                    hit = IntrospectionSupport.setProperty(context, 
context.getTypeConverter(), target, name, value);
-                } catch (IllegalArgumentException e) {
-                    // no we could not and this would be thrown if we 
attempted to set a value on a property which we cannot do type conversion as
-                    // then maybe the value refers to a spring bean in the 
registry so try this
-                    hit = IntrospectionSupport.setProperty(context, 
context.getTypeConverter(), target, name, null, stringValue, true);
+            try {
+                hit = PropertyBindingSupport.bindProperty(context, target, 
name, value);
+            } catch (PropertyBindingException e) {
+                // no we could not and this would be thrown if we attempted to 
set a value on a property which we cannot do type conversion as
+                // then maybe the value refers to a spring bean in the 
registry so try this
+                if (stringValue != null) {
+                    if (stringValue.startsWith("#")) {
+                        stringValue = stringValue.substring(1);
+                    }
+                    // use #bean: to lookup
+                    stringValue = "#bean:" + stringValue;
+                    hit = PropertyBindingSupport.bindProperty(context, target, 
name, stringValue);
                 }
             }
 
diff --git 
a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/util/CamelPropertiesHelperTest.java
 
b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/util/CamelPropertiesHelperTest.java
index 7c8fa8e..b89b657 100644
--- 
a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/util/CamelPropertiesHelperTest.java
+++ 
b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/util/CamelPropertiesHelperTest.java
@@ -57,14 +57,16 @@ public class CamelPropertiesHelperTest {
         }
     }
 
-    static class MyOption {
+    public static class MyOption {
     }
 
-    static class MyClass {
+    public static class MyClass {
 
         private int id;
         private String name;
         private MyOption option;
+        private CamelContext camelContext;
+        private MyFooClass myFooClass;
 
         public int getId() {
             return id;
@@ -89,6 +91,22 @@ public class CamelPropertiesHelperTest {
         public void setOption(MyOption option) {
             this.option = option;
         }
+
+        public CamelContext getCamelContext() {
+            return camelContext;
+        }
+
+        public void setCamelContext(CamelContext camelContext) {
+            this.camelContext = camelContext;
+        }
+
+        public MyFooClass getMyFooClass() {
+            return myFooClass;
+        }
+
+        public void setMyFooClass(MyFooClass myFooClass) {
+            this.myFooClass = myFooClass;
+        }
     }
 
     @Test
@@ -109,6 +127,71 @@ public class CamelPropertiesHelperTest {
     }
 
     @Test
+    public void testSetCamelPropertiesAutowired() throws Exception {
+        MyClass target = new MyClass();
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", "123");
+        map.put("name", "Donald Duck");
+        map.put("option", "myCoolOption");
+        map.put("camelContext", "#autowired");
+
+        CamelPropertiesHelper.setCamelProperties(camelContext, target, map, 
true);
+
+        Assert.assertEquals("Should configure all options", 0, map.size());
+        Assert.assertEquals(123, target.getId());
+        Assert.assertEquals("Donald Duck", target.getName());
+        Assert.assertSame(context.getBean("myCoolOption"), target.getOption());
+        Assert.assertSame(camelContext, target.getCamelContext());
+    }
+
+    @Test
+    public void testSetCamelPropertiesType() throws Exception {
+        MyClass target = new MyClass();
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", "123");
+        map.put("name", "Donald Duck");
+        map.put("option", "myCoolOption");
+        map.put("camelContext", "#type:org.apache.camel.CamelContext");
+
+        CamelPropertiesHelper.setCamelProperties(camelContext, target, map, 
true);
+
+        Assert.assertEquals("Should configure all options", 0, map.size());
+        Assert.assertEquals(123, target.getId());
+        Assert.assertEquals("Donald Duck", target.getName());
+        Assert.assertSame(context.getBean("myCoolOption"), target.getOption());
+        Assert.assertSame(camelContext, target.getCamelContext());
+    }
+
+    @Test
+    public void testSetCamelPropertiesClass() throws Exception {
+        MyClass target = new MyClass();
+
+        // must use linked hash map as we must create foo first before we set 
its name as nested property
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put("id", "123");
+        map.put("name", "Donald Duck");
+        map.put("option", "myCoolOption");
+        map.put("camelContext", "#type:org.apache.camel.CamelContext");
+        map.put("myFooClass", 
"#class:org.apache.camel.spring.boot.util.MyFooClass");
+        map.put("myFooClass.name", "Goofy");
+
+        CamelPropertiesHelper.setCamelProperties(camelContext, target, map, 
true);
+
+        Assert.assertEquals("Should configure all options", 0, map.size());
+        Assert.assertEquals(123, target.getId());
+        Assert.assertEquals("Donald Duck", target.getName());
+        Assert.assertSame(context.getBean("myCoolOption"), target.getOption());
+        Assert.assertSame(camelContext, target.getCamelContext());
+
+        MyFooClass myFooClass = target.getMyFooClass();
+        Assert.assertNotNull(myFooClass);
+        Assert.assertSame(camelContext, myFooClass.getCamelContext());
+        Assert.assertEquals("Goofy", myFooClass.getName());
+    }
+
+    @Test
     public void testSetCamelPropertiesReference() throws Exception {
         MyClass target = new MyClass();
 
diff --git 
a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/util/MyFooClass.java
 
b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/util/MyFooClass.java
new file mode 100644
index 0000000..c50f9f8
--- /dev/null
+++ 
b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/util/MyFooClass.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.spring.boot.util;
+
+import org.apache.camel.CamelContext;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Just a basic class
+ */
+public class MyFooClass {
+
+    private String name;
+    @Autowired
+    private CamelContext camelContext;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+}

Reply via email to