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 8bc1cf2  CAMEL-14955: camel-core - @PropertyInject with primitive 
types should be injected first
8bc1cf2 is described below

commit 8bc1cf288ad77cf3c354942c343a71a95bef5d7c
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Thu Apr 23 10:13:16 2020 +0200

    CAMEL-14955: camel-core - @PropertyInject with primitive types should be 
injected first
---
 .../impl/engine/DefaultCamelBeanPostProcessor.java | 74 +++++++++++++++------
 ...efaultCamelBeanPostProcessorFieldFirstTest.java | 76 ++++++++++++++++++++++
 2 files changed, 131 insertions(+), 19 deletions(-)

diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
index ad395ca..426f21f 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Function;
 
 import org.apache.camel.BeanConfigInject;
 import org.apache.camel.BeanInject;
@@ -85,15 +86,9 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor {
             return bean;
         }
 
-        if (bindToRegistrySupported()) {
-            injectClass(bean, beanName);
-            injectNestedClasses(bean, beanName);
-            injectBindToRegistryFields(bean, beanName);
-            injectBindToRegistryMethods(bean, beanName);
-        }
-
-        injectFields(bean, beanName);
-        injectMethods(bean, beanName);
+        // do bean binding on simple types first, and then afterwards on 
complex types
+        injectFirstPass(bean, beanName, type -> !isComplexUserType(type));
+        injectSecondPass(bean, beanName, type -> isComplexUserType(type));
 
         if (bean instanceof CamelContextAware && canSetCamelContext(bean, 
beanName)) {
             CamelContextAware contextAware = (CamelContextAware)bean;
@@ -174,14 +169,38 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor {
         return true;
     }
 
-    /**
-     * A strategy method to allow implementations to perform some custom JBI
-     * based injection of the POJO
-     *
-     * @param bean the bean to be injected
-     */
-    protected void injectFields(final Object bean, final String beanName) {
+    protected void injectFirstPass(Object bean, String beanName, 
Function<Class, Boolean> filter) {
+        // on first pass do field and methods first
+        injectFields(bean, beanName, filter);
+        injectMethods(bean, beanName, filter);
+
+        if (bindToRegistrySupported()) {
+            injectClass(bean, beanName);
+            injectNestedClasses(bean, beanName);
+            injectBindToRegistryFields(bean, beanName, filter);
+            injectBindToRegistryMethods(bean, beanName, filter);
+        }
+    }
+
+    protected void injectSecondPass(Object bean, String beanName, 
Function<Class, Boolean> filter) {
+        // on second pass do bind to registry beforehand as they may be used 
by field/method injections below
+        if (bindToRegistrySupported()) {
+            injectClass(bean, beanName);
+            injectNestedClasses(bean, beanName);
+            injectBindToRegistryFields(bean, beanName, filter);
+            injectBindToRegistryMethods(bean, beanName, filter);
+        }
+
+        injectFields(bean, beanName, filter);
+        injectMethods(bean, beanName, filter);
+    }
+
+    protected void injectFields(final Object bean, final String beanName, 
Function<Class, Boolean> accept) {
         ReflectionHelper.doWithFields(bean.getClass(), field -> {
+            if (accept != null && !accept.apply(field.getType())) {
+                return;
+            }
+
             PropertyInject propertyInject = 
field.getAnnotation(PropertyInject.class);
             if (propertyInject != null) {
                 injectFieldProperty(field, propertyInject.value(), 
propertyInject.defaultValue(), bean, beanName);
@@ -213,8 +232,12 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor {
         });
     }
 
-    protected void injectBindToRegistryFields(final Object bean, final String 
beanName) {
+    protected void injectBindToRegistryFields(final Object bean, final String 
beanName, Function<Class, Boolean> accept) {
         ReflectionHelper.doWithFields(bean.getClass(), field -> {
+            if (accept != null && !accept.apply(field.getType())) {
+                return;
+            }
+
             BindToRegistry bind = field.getAnnotation(BindToRegistry.class);
             if (bind != null) {
                 bindToRegistry(field, bind.value(), bean, beanName, 
bind.beanPostProcess());
@@ -250,18 +273,26 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor {
                         field.getName(), bean, beanName));
     }
 
-    protected void injectMethods(final Object bean, final String beanName) {
+    protected void injectMethods(final Object bean, final String beanName, 
Function<Class, Boolean> accept) {
         ReflectionHelper.doWithMethods(bean.getClass(), method -> {
+            if (accept != null && !accept.apply(method.getReturnType())) {
+                return;
+            }
+
             setterInjection(method, bean, beanName);
             getPostProcessorHelper().consumerInjection(method, bean, beanName);
         });
     }
 
-    protected void injectBindToRegistryMethods(final Object bean, final String 
beanName) {
+    protected void injectBindToRegistryMethods(final Object bean, final String 
beanName, Function<Class, Boolean> accept) {
         // sort the methods so the simplest are used first
 
         final List<Method> methods = new ArrayList<>();
         ReflectionHelper.doWithMethods(bean.getClass(), method -> {
+            if (accept != null && !accept.apply(method.getReturnType())) {
+                return;
+            }
+
             BindToRegistry bind = method.getAnnotation(BindToRegistry.class);
             if (bind != null) {
                 methods.add(method);
@@ -521,4 +552,9 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor {
         return parameters;
     }
 
+    private static boolean isComplexUserType(Class type) {
+        // lets consider all non java, as complex types
+        return type != null && !type.isPrimitive() && 
!type.getName().startsWith("java.");
+    }
+
 }
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelBeanPostProcessorFieldFirstTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelBeanPostProcessorFieldFirstTest.java
new file mode 100644
index 0000000..447fa90
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelBeanPostProcessorFieldFirstTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.impl;
+
+import java.util.Properties;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.PropertyInject;
+import org.apache.camel.spi.CamelBeanPostProcessor;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DefaultCamelBeanPostProcessorFieldFirstTest extends 
ContextTestSupport {
+
+    private CamelBeanPostProcessor postProcessor;
+
+    @Test
+    public void testPostProcessor() throws Exception {
+        FooService foo = new FooService();
+
+        Properties prop = new Properties();
+        prop.setProperty("foo", "Donald Duck");
+        context.getPropertiesComponent().setInitialProperties(prop);
+
+        postProcessor.postProcessBeforeInitialization(foo, "foo");
+        postProcessor.postProcessAfterInitialization(foo, "foo");
+
+        // should register the beans in the registry via @BindRegistry
+        Object bean = context.getRegistry().lookupByName("myCoolBean");
+        assertNotNull(bean);
+        MySerialBean msb = assertIsInstanceOf(MySerialBean.class, bean);
+
+        assertEquals(123, msb.getId());
+        assertEquals("Donald Duck", msb.getName());
+    }
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        postProcessor = 
context.adapt(ExtendedCamelContext.class).getBeanPostProcessor();
+    }
+
+    @BindToRegistry
+    public class FooService {
+
+        // should inject simple types first such as this property
+        @PropertyInject("foo")
+        private String foo;
+
+        @BindToRegistry("myCoolBean")
+        public MySerialBean myBean() {
+            MySerialBean myBean = new MySerialBean();
+            myBean.setId(123);
+            myBean.setName(foo);
+            return myBean;
+        }
+
+    }
+}

Reply via email to