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
The following commit(s) were added to refs/heads/master by this push:
new a35e72f CAMEL-13557: Add property binding support to make it
convenient to configure components and whatnot.
a35e72f is described below
commit a35e72fdbce8d3546d1d285a39eb2cde831ac755
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri May 24 13:12:08 2019 +0200
CAMEL-13557: Add property binding support to make it convenient to
configure components and whatnot.
---
.../camel/main/MainConfigurationProperties.java | 15 +++
.../java/org/apache/camel/main/MainSupport.java | 6 +-
.../PropertyBindingSupportAutowireNestedTest.java | 135 +++++++++++++++++++++
.../camel/support/PropertyBindingSupport.java | 29 ++++-
4 files changed, 179 insertions(+), 6 deletions(-)
diff --git
a/core/camel-core/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
b/core/camel-core/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index 831dd97..9e7e418 100644
---
a/core/camel-core/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++
b/core/camel-core/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -25,6 +25,7 @@ import org.apache.camel.spi.ReloadStrategy;
public class MainConfigurationProperties {
private boolean autoConfigurationEnabled = true;
+ private boolean autowireComponentProperties = true;
private String name;
private int shutdownTimeout = 300;
private boolean shutdownSuppressLoggingOnTimeout;
@@ -102,6 +103,20 @@ public class MainConfigurationProperties {
this.autoConfigurationEnabled = autoConfigurationEnabled;
}
+ public boolean isAutowireComponentProperties() {
+ return autowireComponentProperties;
+ }
+
+ /**
+ * Whether autowiring components with properties that are of same type,
which has been added to the Camel registry, as a singleton instance.
+ * This is used for convention over configuration to inject DataSource,
AmazonLogin instances to the components.
+ * <p/>
+ * This option is default enabled.
+ */
+ public void setAutowireComponentProperties(boolean
autowireComponentProperties) {
+ this.autowireComponentProperties = autowireComponentProperties;
+ }
+
public String getName() {
return name;
}
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 1866caf..c1a4a8a 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
@@ -852,8 +852,10 @@ public abstract class MainSupport extends ServiceSupport {
// conventional configuration via properties to allow configuring
options on
// component, dataformat, and languages (like spring-boot
auto-configuration)
- if (mainConfigurationProperties.isAutoConfigurationEnabled()) {
+ if (mainConfigurationProperties.isAutowireComponentProperties()) {
autoConfigurationFromRegistry(camelContext);
+ }
+ if (mainConfigurationProperties.isAutoConfigurationEnabled()) {
autoConfigurationFromProperties(camelContext);
}
@@ -1270,7 +1272,7 @@ public abstract class MainSupport extends ServiceSupport {
@Override
public void onComponentAdd(String name, Component component) {
PropertyBindingSupport.autowireSingletonPropertiesFromRegistry(camelContext,
component, false, (obj, propertyName, type, value) -> {
- LOG.info("Auto configuring option: {} on component: {} as
one instance of type: {} registered in the Camel Registry", propertyName, obj,
type.getName());
+ LOG.info("Auto configuring option: {} on component: {} as
one instance of type: {} registered in the Camel Registry", propertyName,
component.getClass().getSimpleName(), type.getName());
});
}
});
diff --git
a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportAutowireNestedTest.java
b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportAutowireNestedTest.java
new file mode 100644
index 0000000..84ab322
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportAutowireNestedTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.support;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.junit.Test;
+
+/**
+ * Unit test for PropertyBindingSupport
+ */
+public class PropertyBindingSupportAutowireNestedTest extends
ContextTestSupport {
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+
+ Company work = new Company();
+ work.setId(456);
+ work.setName("Acme");
+ context.getRegistry().bind("myWork", work);
+
+ return context;
+ }
+
+ @Test
+ public void testAutowireProperties() 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.gold-customer",
"true");
+
PropertyBindingSupport.autowireSingletonPropertiesFromRegistry(context, foo);
+
+ assertEquals("James", foo.getName());
+ assertEquals(33, foo.getBar().getAge());
+ assertTrue(foo.getBar().isRider());
+ assertTrue(foo.getBar().isGoldCustomer());
+ // should be auto wired
+ assertNotNull(foo.getBar().getWork());
+ assertEquals(456, foo.getBar().getWork().getId());
+ assertEquals("Acme", foo.getBar().getWork().getName());
+ }
+
+ public static class Foo {
+ private String name;
+ private Bar bar = new Bar(this);
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Bar getBar() {
+ return bar;
+ }
+
+ public void setBar(Bar bar) {
+ this.bar = bar;
+ }
+ }
+
+ public static class Bar {
+ private Foo parent;
+ private int age;
+ private boolean rider;
+ private Company work;
+ private boolean goldCustomer;
+
+ public Bar(Foo parent) {
+ this.parent = parent;
+ }
+
+ public Foo getParent() {
+ // circular dependency foo -> bar && bar -> foo
+ return parent;
+ }
+
+ public void setParent(Foo parent) {
+ this.parent = parent;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public boolean isRider() {
+ return rider;
+ }
+
+ public void setRider(boolean rider) {
+ this.rider = rider;
+ }
+
+ public Company getWork() {
+ return work;
+ }
+
+ public void setWork(Company work) {
+ this.work = work;
+ }
+
+ public boolean isGoldCustomer() {
+ return goldCustomer;
+ }
+
+ public void setGoldCustomer(boolean goldCustomer) {
+ this.goldCustomer = goldCustomer;
+ }
+ }
+
+}
+
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 cddf4fe..7a21929 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
@@ -17,13 +17,17 @@
package org.apache.camel.support;
import java.lang.reflect.Method;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.ExtendedCamelContext;
import org.apache.camel.PropertyBindingException;
+import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
import static org.apache.camel.support.IntrospectionSupport.findSetterMethods;
import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
@@ -165,7 +169,8 @@ public final class PropertyBindingSupport {
public static boolean autowireSingletonPropertiesFromRegistry(CamelContext
camelContext, Object target, boolean bindNullOnly, OnAutowiring callback) {
try {
if (target != null) {
- return doAutowireSingletonPropertiesFromRegistry(camelContext,
target, bindNullOnly, callback);
+ Set<Object> parents = new HashSet<>();
+ return doAutowireSingletonPropertiesFromRegistry(camelContext,
target, parents, bindNullOnly, callback);
}
} catch (Exception e) {
throw new PropertyBindingException(target, e);
@@ -174,7 +179,8 @@ public final class PropertyBindingSupport {
return false;
}
- private static boolean
doAutowireSingletonPropertiesFromRegistry(CamelContext camelContext, Object
target, boolean bindNullOnly, OnAutowiring callback) throws Exception {
+ private static boolean
doAutowireSingletonPropertiesFromRegistry(CamelContext camelContext, Object
target, Set<Object> parents,
+ boolean
bindNullOnly, OnAutowiring callback) throws Exception {
// when adding a component then support auto-configuring complex types
// by looking up from registry, such as DataSource etc
Map<String, Object> properties = new LinkedHashMap<>();
@@ -182,12 +188,18 @@ public final class PropertyBindingSupport {
boolean hit = false;
- // TODO: add support for nesting but not for inherited properties from
base classes (eg CamelContext etc)
-
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
Class<?> type = getGetterType(target, key);
+
+ boolean skip = parents.contains(value) || value instanceof
CamelContext;
+ if (skip) {
+ // we have already covered this as parent of parents so dont
walk down this as we want to avoid
+ // circular dependencies when walking the OGNL graph, also we
dont want to walk down CamelContext
+ continue;
+ }
+
if (isComplexUserType(type)) {
// if the property has not been set and its a complex type
(not simple or string etc)
if (!bindNullOnly || value == null) {
@@ -202,6 +214,15 @@ public final class PropertyBindingSupport {
}
}
}
+
+ // TODO: Support creating new instances to walk down the tree
if its null
+
+ // remember this as parent and also autowire nested properties
+ // do not walk down if it point to our-selves (circular
reference)
+ if (value != null) {
+ parents.add(target);
+ hit |=
doAutowireSingletonPropertiesFromRegistry(camelContext, value, parents,
bindNullOnly, callback);
+ }
}
};