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/23 19:30:54 UTC

[camel] 08/18: 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 13557
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 5ac8ff8a4f600d65d009afb5687f2aeb8990bc8a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu May 23 07:54:29 2019 +0200

    CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.
---
 .../org/apache/camel/PropertyBindingException.java |  46 +++++++++
 .../camel/support/PropertyBindingSupportTest.java  |  19 ++++
 .../camel/support/PropertyBindingSupport.java      | 114 ++++++++++++---------
 3 files changed, 131 insertions(+), 48 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/PropertyBindingException.java b/core/camel-api/src/main/java/org/apache/camel/PropertyBindingException.java
new file mode 100644
index 0000000..ed6e61b
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/PropertyBindingException.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;
+
+/**
+ * Error binding property to a bean.
+ */
+public class PropertyBindingException extends RuntimeCamelException {
+
+    private final Object target;
+    private final String propertyName;
+
+    public PropertyBindingException(Object target, String propertyName) {
+        super("No such property: " + propertyName + " on bean: " + target);
+        this.target = target;
+        this.propertyName = propertyName;
+    }
+
+    public PropertyBindingException(Object target, String propertyName, Exception e) {
+        super("Error binding property: " + propertyName + " on bean: " + target, e);
+        this.target = target;
+        this.propertyName = propertyName;
+    }
+
+    public Object getTarget() {
+        return target;
+    }
+
+    public String getPropertyName() {
+        return propertyName;
+    }
+}
diff --git a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
index e6e4245..b3f32c7 100644
--- a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
@@ -22,6 +22,7 @@ import java.util.Properties;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ContextTestSupport;
+import org.apache.camel.PropertyBindingException;
 import org.junit.Test;
 
 /**
@@ -142,6 +143,24 @@ public class PropertyBindingSupportTest extends ContextTestSupport {
         assertEquals(null, foo.getBar().getWork().getName());
     }
 
+    @Test
+    public void testMandatory() throws Exception {
+        Foo foo = new Foo();
+
+        PropertyBindingSupport.bindMandatoryProperty(context, foo, "name", "James");
+
+        boolean bound = PropertyBindingSupport.bindProperty(context, foo, "bar.myAge", "33");
+        assertFalse(bound);
+
+        try {
+            PropertyBindingSupport.bindMandatoryProperty(context, foo, "bar.myAge", "33");
+            fail("Should have thrown exception");
+        } catch (PropertyBindingException e) {
+            assertEquals("bar.myAge", e.getPropertyName());
+            assertSame(foo, e.getTarget());
+        }
+    }
+
     public static class Foo {
         private String name;
         private Bar bar = new Bar();
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 1577b14..5d06df4 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
@@ -1,13 +1,13 @@
-/**
+/*
  * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ *
+ *      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.
@@ -21,7 +21,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.PropertyBindingException;
 
 import static org.apache.camel.support.IntrospectionSupport.findSetterMethods;
 import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
@@ -41,7 +41,7 @@ import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
 public final class PropertyBindingSupport {
 
     // TODO: Add support for auto binding to singleton instance by type from registry (boolean on|off)
-    // TODO: Better exception message if something goes wrong (output target, name of property etc)
+    // TODO: Add support for Map/List
 
     private PropertyBindingSupport() {
     }
@@ -52,12 +52,12 @@ public final class PropertyBindingSupport {
      * @param camelContext  the camel context
      * @param target        the target object
      * @param properties    the properties
-     * @return              true if one or more properties was bound, false otherwise
+     * @return              true if all the properties was bound, false otherwise
      */
-    public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties) throws Exception {
-        boolean answer = false;
+    public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties) {
+        boolean answer = true;
         for (Map.Entry<String, Object> entry : properties.entrySet()) {
-            answer |= bindProperty(camelContext, target, entry.getKey(), entry.getValue());
+            answer &= bindProperty(camelContext, target, entry.getKey(), entry.getValue());
         }
         return answer;
     }
@@ -71,15 +71,40 @@ public final class PropertyBindingSupport {
      * @param value         value of property
      * @return              true if property was bound, false otherwise
      */
-    public static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value) throws Exception {
-        if (target != null && name != null) {
-            return setProperty(camelContext, target, name, value);
-        } else {
-            return false;
+    public static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value) {
+        try {
+            if (target != null && name != null) {
+                return setProperty(camelContext, target, name, value);
+            }
+        } catch (Exception e) {
+            throw new PropertyBindingException(target, name, e);
         }
+
+        return false;
     }
 
-    private static boolean setProperty(CamelContext context, Object target, String name, Object value) {
+    /**
+     * Binds the mandatory property to the target object (will fail if not set/bound).
+     *
+     * @param camelContext  the camel context
+     * @param target        the target object
+     * @param name          name of property
+     * @param value         value of property
+     */
+    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);
+                if (!bound) {
+                    throw new PropertyBindingException(target, name);
+                }
+            }
+        } catch (Exception e) {
+            throw new PropertyBindingException(target, name, e);
+        }
+    }
+
+    private static boolean setProperty(CamelContext context, Object target, String name, Object value) throws Exception {
         Class<?> clazz = target.getClass();
         String refName = null;
 
@@ -120,43 +145,36 @@ public final class PropertyBindingSupport {
                 }
             }
             // okay we found a nested property, then lets change to use that
-            try {
-                target = newTarget;
-                name = parts[parts.length - 1];
-                if (value instanceof String) {
-                    if (value.toString().startsWith("class:")) {
-                        // its a new class to be created
-                        String className = value.toString().substring(6);
-                        Class<?> type = context.getClassResolver().resolveMandatoryClass(className);
-                        if (type != null) {
-                            value = context.getInjector().newInstance(type);
-                        }
-                    } else if (value.toString().startsWith("#type:")) {
-                        // its reference by type, so lookup the actual value and use it if there is only one instance in the registry
-                        String typeName = value.toString().substring(6);
-                        Class<?> type = context.getClassResolver().resolveMandatoryClass(typeName);
-                        if (type != null) {
-                            Set<?> types = context.getRegistry().findByType(type);
-                            if (types.size() == 1) {
-                                value = types.iterator().next();
-                            }
-                        }
-                    } else if (EndpointHelper.isReferenceParameter(value.toString())) {
-                        // okay its a reference so swap to lookup this which is already supported in IntrospectionSupport
-                        refName = value.toString();
-                        value = null;
+            target = newTarget;
+            name = parts[parts.length - 1];
+        }
+
+        if (value instanceof String) {
+            if (value.toString().startsWith("class:")) {
+                // its a new class to be created
+                String className = value.toString().substring(6);
+                Class<?> type = context.getClassResolver().resolveMandatoryClass(className);
+                if (type != null) {
+                    value = context.getInjector().newInstance(type);
+                }
+            } else if (value.toString().startsWith("#type:")) {
+                // its reference by type, so lookup the actual value and use it if there is only one instance in the registry
+                String typeName = value.toString().substring(6);
+                Class<?> type = context.getClassResolver().resolveMandatoryClass(typeName);
+                if (type != null) {
+                    Set<?> types = context.getRegistry().findByType(type);
+                    if (types.size() == 1) {
+                        value = types.iterator().next();
                     }
                 }
-            } catch (Exception e) {
-                throw RuntimeCamelException.wrapRuntimeException(e);
+            } else if (EndpointHelper.isReferenceParameter(value.toString())) {
+                // okay its a reference so swap to lookup this which is already supported in IntrospectionSupport
+                refName = value.toString();
+                value = null;
             }
         }
 
-        try {
-            return IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, true);
-        } catch (Exception e) {
-            throw RuntimeCamelException.wrapRuntimeException(e);
-        }
+        return IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, true);
     }
 
 }