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:46 UTC
[camel] 06/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 9af09b9676e3c6364f048b71ce2597df09d028ce
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu May 23 06:38:33 2019 +0200
CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.
---
.../java/org/apache/camel/main/MainSupport.java | 2 +
.../camel/support/PropertyBindingSupportTest.java | 37 +++++++++++--
.../camel/support/PropertyBindingSupport.java | 61 +++++++++++++++-------
3 files changed, 78 insertions(+), 22 deletions(-)
diff --git a/core/camel-core/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-core/src/main/java/org/apache/camel/main/MainSupport.java
index fedb2cd..4a249dc 100644
--- a/core/camel-core/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-core/src/main/java/org/apache/camel/main/MainSupport.java
@@ -1261,6 +1261,8 @@ public abstract class MainSupport extends ServiceSupport {
IntrospectionSupport.getProperties(component, properties, null);
// TODO: Use PropertyBindingSupport to make it support this kind of use-case too
+ // TODO: Allow nested properties too
+ // TODO: Allow fluent builders
// lookup complex types
properties.forEach((k, v) -> {
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 86118be..3f28037 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
@@ -16,12 +16,16 @@
*/
package org.apache.camel.support;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
import org.apache.camel.CamelContext;
import org.apache.camel.ContextTestSupport;
import org.junit.Test;
/**
- * Unit test for PropertyBindingSupport with nested properties
+ * Unit test for PropertyBindingSupport
*/
public class PropertyBindingSupportTest extends ContextTestSupport {
@@ -34,19 +38,46 @@ public class PropertyBindingSupportTest extends ContextTestSupport {
work.setName("Acme");
context.getRegistry().bind("myWork", work);
+ Properties placeholders = new Properties();
+ placeholders.put("companyName", "Acme");
+ placeholders.put("committer", "rider");
+ context.getPropertiesComponent().setInitialProperties(placeholders);
+
return context;
}
@Test
+ public void testProperties() throws Exception {
+ Foo foo = new Foo();
+
+ Map<String, Object> prop = new HashMap<>();
+ prop.put("name", "James");
+ prop.put("bar.age", "33");
+ prop.put("bar.{{committer}}", "true");
+ prop.put("bar.gold-customer", "true");
+ prop.put("bar.work.id", "123");
+ prop.put("bar.work.name", "{{companyName}}");
+
+ PropertyBindingSupport.bindProperties(context, foo, prop);
+
+ assertEquals("James", foo.getName());
+ assertEquals(33, foo.getBar().getAge());
+ assertTrue(foo.getBar().isRider());
+ assertTrue(foo.getBar().isGoldCustomer());
+ assertEquals(123, foo.getBar().getWork().getId());
+ assertEquals("Acme", foo.getBar().getWork().getName());
+ }
+
+ @Test
public void testNested() throws Exception {
Foo foo = new Foo();
PropertyBindingSupport.bindProperty(context, foo, "name", "James");
PropertyBindingSupport.bindProperty(context, foo, "bar.age", "33");
- PropertyBindingSupport.bindProperty(context, foo, "bar.rider", "true");
+ PropertyBindingSupport.bindProperty(context, foo, "bar.{{committer}}", "true");
PropertyBindingSupport.bindProperty(context, foo, "bar.gold-customer", "true");
PropertyBindingSupport.bindProperty(context, foo, "bar.work.id", "123");
- PropertyBindingSupport.bindProperty(context, foo, "bar.work.name", "Acme");
+ PropertyBindingSupport.bindProperty(context, foo, "bar.work.name", "{{companyName}}");
assertEquals("James", foo.getName());
assertEquals(33, foo.getBar().getAge());
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 66bb0b4..d9bfb03 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
@@ -21,6 +21,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.camel.CamelContext;
+import org.apache.camel.RuntimeCamelException;
import static org.apache.camel.support.IntrospectionSupport.findSetterMethods;
import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
@@ -29,6 +30,7 @@ import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
* A convenient support class for binding String valued properties to an instance which
* uses a set of conventions:
* <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>reference by id - Values can refer to other beans in the registry by prefixing with # syntax, eg #myBean</li>
* </ul>
@@ -41,34 +43,52 @@ public final class PropertyBindingSupport {
private PropertyBindingSupport() {
}
+ /**
+ * Binds the properties to the target object.
+ *
+ * @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
+ */
public static boolean bindProperties(CamelContext camelContext, Object target, Map<String, Object> properties) throws Exception {
- boolean answer = true;
+ boolean answer = false;
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;
}
- public static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value) throws Exception {
- return setProperty(camelContext, target, name, value, null, true, true);
- }
-
/**
- * This method supports two modes to set a property:
- *
- * 1. Setting a property that has already been resolved, this is the case when {@code context} and {@code refName} are
- * NULL and {@code value} is non-NULL.
+ * Binds the property to the target object.
*
- * 2. Setting a property that has not yet been resolved, the property will be resolved based on the suitable methods
- * found matching the property name on the {@code target} bean. For this mode to be triggered the parameters
- * {@code context} and {@code refName} must NOT be NULL, and {@code value} MUST be NULL.
+ * @param camelContext the camel context
+ * @param target the target object
+ * @param name name of property
+ * @param value value of property
+ * @return true if property was bound, false otherwise
*/
- private static boolean setProperty(CamelContext context, Object target, String name, Object value, String refName,
- boolean allowBuilderPattern, boolean allowNestedProperties) throws Exception {
+ 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;
+ }
+ }
+
+ private static boolean setProperty(CamelContext context, Object target, String name, Object value) {
Class<?> clazz = target.getClass();
+ String refName = null;
+
+ // resolve property placeholders
+ 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 (allowNestedProperties && name.indexOf('.') > 0) {
+ if (name.indexOf('.') > 0) {
String[] parts = name.split("\\.");
Object newTarget = target;
Class<?> newClass = clazz;
@@ -78,7 +98,7 @@ public final class PropertyBindingSupport {
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
- Set<Method> newSetters = findSetterMethods(newClass, part, allowBuilderPattern);
+ Set<Method> newSetters = findSetterMethods(newClass, part, true);
if (newSetters.size() == 1) {
Method method = newSetters.iterator().next();
Class<?> parameterType = method.getParameterTypes()[0];
@@ -98,7 +118,6 @@ public final class PropertyBindingSupport {
}
// okay we found a nested property, then lets change to use that
target = newTarget;
- clazz = newTarget.getClass();
name = parts[parts.length - 1];
if (value instanceof String) {
if (EndpointHelper.isReferenceParameter(value.toString())) {
@@ -109,7 +128,11 @@ public final class PropertyBindingSupport {
}
}
- return IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, allowBuilderPattern);
+ try {
+ return IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, true);
+ } catch (Exception e) {
+ throw RuntimeCamelException.wrapRuntimeException(e);
+ }
}
}