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 <[email protected]>
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");
+ }
+ }
+}