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 <claus.ib...@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); } }