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 511a773  CAMEL-13582: Camel main - Configuration class should support 
automatic autowire by type. Made CamelBeanPostProcessor sort the 
@BindToRegistry methods in a better order so they deal with inter dependencies 
among themselves.
511a773 is described below

commit 511a7730ba4d2a9c27d0d27bb5bd815653d2898b
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Mon May 27 12:28:03 2019 +0200

    CAMEL-13582: Camel main - Configuration class should support automatic 
autowire by type. Made CamelBeanPostProcessor sort the @BindToRegistry methods 
in a better order so they deal with inter dependencies among themselves.
---
 .../impl/engine/DefaultCamelBeanPostProcessor.java |  28 +++++-
 .../main/MainIoCNewRouteBuilderComplexTest.java    | 102 +++++++++++++++++++++
 2 files changed, 129 insertions(+), 1 deletion(-)

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 cab3f8b..6899089 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
@@ -247,6 +247,32 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor {
         // sort methods on shortest number of parameters as we want to process 
the most simplest first
         methods.sort(Comparator.comparingInt(Method::getParameterCount));
 
+        // then do a more complex sorting where we check inter-dependency 
among the methods
+        methods.sort((m1, m2) -> {
+            Class[] types1 = m1.getParameterTypes();
+            Class[] types2 = m2.getParameterTypes();
+
+            // favour methods that has no parameters
+            if (types1.length == 0 && types2.length == 0) {
+                return 0;
+            } else if (types1.length == 0) {
+                return -1;
+            } else if (types2.length == 0) {
+                return 1;
+            }
+
+            // okay then compare so we favour methods that does not use 
parameter types that are returned from other methods
+            boolean usedByOthers1 = false;
+            for (Class clazz : types1) {
+                usedByOthers1 |= methods.stream().anyMatch(m -> 
m.getParameterCount() > 0 && clazz.isAssignableFrom(m.getReturnType()));
+            }
+            boolean usedByOthers2 = false;
+            for (Class clazz : types2) {
+                usedByOthers2 |= methods.stream().anyMatch(m -> 
m.getParameterCount() > 0 && clazz.isAssignableFrom(m.getReturnType()));
+            }
+            return Boolean.compare(usedByOthers1, usedByOthers2);
+        });
+
         LOG.trace("Discovered {} @BindToRegistry methods", methods.size());
 
         // bind each method
@@ -442,7 +468,7 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor {
                     Set<?> instances = 
camelContext.getRegistry().findByType(type);
                     if (instances.size() == 1) {
                         parameters[i] = instances.iterator().next();
-                    } else {
+                    } else if (instances.size() > 1) {
                         // there are multiple instances of the same type, so 
barf
                         throw new IllegalArgumentException("Multiple beans of 
the same type: " + type
                                 + " exists in the Camel registry. Specify the 
bean name on @BeanInject to bind to a single bean, at the method: " + method);
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/main/MainIoCNewRouteBuilderComplexTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/main/MainIoCNewRouteBuilderComplexTest.java
new file mode 100644
index 0000000..01a90db
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/main/MainIoCNewRouteBuilderComplexTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.main;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.MyFoo;
+import org.apache.camel.PropertyInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MainIoCNewRouteBuilderComplexTest extends Assert {
+
+    @Test
+    public void testMainIoC() throws Exception {
+        Main main = new Main();
+        main.addRouteBuilder(new MyRouteBuilder());
+        main.start();
+
+        CamelContext camelContext = main.getCamelContext();
+        assertNotNull(camelContext);
+
+        MockEndpoint endpoint = camelContext.getEndpoint("mock:results", 
MockEndpoint.class);
+        endpoint.expectedBodiesReceived("Hi dude");
+
+        main.getCamelTemplate().sendBody("direct:start", 
"<message>1</message>");
+
+        endpoint.assertIsSatisfied();
+
+        main.stop();
+    }
+
+    public static class MyBar {
+
+        private final String name;
+
+        public MyBar(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    public static class MyDude {
+
+        private final String name;
+
+        public MyDude(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    public static class MyRouteBuilder extends RouteBuilder {
+
+        @BindToRegistry("foo")
+        public MyFoo createFoo(MyBar bar) {
+            // should be invoked #3
+            return new MyFoo(bar.toString());
+        }
+
+        @BindToRegistry
+        public MyDude myDude() {
+            // should be invoked #1
+            return new MyDude("dude");
+        }
+
+        @BindToRegistry("bar")
+        public MyBar createBar(@PropertyInject(value = "bye", defaultValue = 
"Hi") String hello, MyDude dude) {
+            // should be invoked #2
+            return new MyBar(hello + " " + dude.name);
+        }
+
+        @Override
+        public void configure() throws Exception {
+            from("direct:start").bean("foo", "getName").to("mock:results");
+        }
+    }
+}

Reply via email to