You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/10/26 10:28:34 UTC
[camel] 03/04: CAMEL-20042: camel-spring - Autowire @Primary beans supported
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch primary-spring
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 658a3790542bffa63c45a029987f9d988c70f0c9
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 26 12:20:02 2023 +0200
CAMEL-20042: camel-spring - Autowire @Primary beans supported
---
.../org/apache/camel/spring/primary/Customer.java | 23 ++++++
.../apache/camel/spring/primary/CustomerImpl.java | 31 ++++++++
.../camel/spring/primary/FindSingleByTypeTest.java | 83 ++++++++++++++++++++++
.../org/apache/camel/spring/primary/MyService.java | 36 ++++++++++
.../apache/camel/spring/primary/findBySingle.xml | 38 ++++++++++
.../spi/ApplicationContextBeanRepository.java | 13 ----
.../java/org/apache/camel/spi/BeanRepository.java | 9 ++-
.../org/apache/camel/support/DefaultRegistry.java | 26 +++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_2.adoc | 15 +++-
9 files changed, 255 insertions(+), 19 deletions(-)
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/Customer.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/Customer.java
new file mode 100644
index 00000000000..283f848bbbd
--- /dev/null
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/Customer.java
@@ -0,0 +1,23 @@
+/*
+ * 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.spring.primary;
+
+public interface Customer {
+
+ String name();
+
+}
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/CustomerImpl.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/CustomerImpl.java
new file mode 100644
index 00000000000..bbe788beb8c
--- /dev/null
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/CustomerImpl.java
@@ -0,0 +1,31 @@
+/*
+ * 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.spring.primary;
+
+public class CustomerImpl implements Customer {
+
+ private final String name;
+
+ public CustomerImpl(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+}
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/FindSingleByTypeTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/FindSingleByTypeTest.java
new file mode 100644
index 00000000000..d72feb88fb0
--- /dev/null
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/FindSingleByTypeTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.spring.primary;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.NoSuchBeanTypeException;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.spi.UuidGenerator;
+import org.apache.camel.util.IOHelper;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class FindSingleByTypeTest extends ContextTestSupport {
+
+ private AbstractApplicationContext applicationContext;
+
+ @Override
+ @BeforeEach
+ public void setUp() throws Exception {
+ super.setUp();
+ if (context != null) {
+ context.stop();
+ }
+ applicationContext = new ClassPathXmlApplicationContext("org/apache/camel/spring/primary/findBySingle.xml");
+ context = applicationContext.getBean("myCamel", ModelCamelContext.class);
+ }
+
+ @Override
+ @AfterEach
+ public void tearDown() throws Exception {
+ // we're done so let's properly close the application context
+ IOHelper.close(applicationContext);
+
+ super.tearDown();
+ }
+
+ @Test
+ public void testFindSingle() {
+ // should find primary
+ Customer c = context.getRegistry().findSingleByType(Customer.class);
+
+ Assertions.assertNotNull(c);
+ Assertions.assertEquals("Donald", c.name());
+
+ // should not find anything
+ Object o = context.getRegistry().findSingleByType(UuidGenerator.class);
+ Assertions.assertNull(o);
+ }
+
+ @Test
+ public void testFindSingleMandatory() {
+ // should find primary
+ Customer c = context.getRegistry().mandatoryFindSingleByType(Customer.class);
+ Assertions.assertEquals("Donald", c.name());
+
+ // should not find anything
+ try {
+ context.getRegistry().mandatoryFindSingleByType(UuidGenerator.class);
+ Assertions.fail("Should throw exception");
+ } catch (NoSuchBeanTypeException e) {
+ // expected
+ }
+ }
+
+}
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/MyService.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/MyService.java
new file mode 100644
index 00000000000..a458b2cca4b
--- /dev/null
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/MyService.java
@@ -0,0 +1,36 @@
+/*
+ * 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.spring.primary;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MyService {
+
+ @Bean
+ @Primary
+ public Customer goodCustomer() {
+ return new CustomerImpl("Donald");
+ }
+
+ @Bean
+ public Customer badCustomer() {
+ return new CustomerImpl("Jack");
+ }
+}
diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/primary/findBySingle.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/primary/findBySingle.xml
new file mode 100644
index 00000000000..199b59ae39f
--- /dev/null
+++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/primary/findBySingle.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://camel.apache.org/schema/spring
+ http://camel.apache.org/schema/spring/camel-spring.xsd
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd">
+
+ <context:component-scan base-package="org.apache.camel.spring.primary"/>
+
+ <!-- empty -->
+ <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/spring">
+ <jmxAgent id="jmx" disabled="true"/>
+ </camelContext>
+
+
+</beans>
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/ApplicationContextBeanRepository.java b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/ApplicationContextBeanRepository.java
index f659bbcecfc..7cfd6923c15 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/ApplicationContextBeanRepository.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/ApplicationContextBeanRepository.java
@@ -21,12 +21,10 @@ import java.util.Map;
import java.util.Set;
import org.apache.camel.NoSuchBeanException;
-import org.apache.camel.NoSuchBeanTypeException;
import org.apache.camel.spi.BeanRepository;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
-import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.config.NamedBeanHolder;
import org.springframework.context.ApplicationContext;
@@ -96,15 +94,4 @@ public class ApplicationContextBeanRepository implements BeanRepository {
}
}
- @Override
- public <T> T mandatoryFindSingleByType(Class<T> type) {
- try {
- NamedBeanHolder<T> holder = applicationContext.getAutowireCapableBeanFactory().resolveNamedBean(type);
- return holder.getBeanInstance();
- } catch (NoUniqueBeanDefinitionException e) {
- throw new NoSuchBeanTypeException(type, e.getNumberOfBeansFound());
- } catch (NoSuchBeanDefinitionException e) {
- throw new NoSuchBeanTypeException(type);
- }
- }
}
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/BeanRepository.java b/core/camel-api/src/main/java/org/apache/camel/spi/BeanRepository.java
index fb875d2812f..ecb9ab93675 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/BeanRepository.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/BeanRepository.java
@@ -88,12 +88,11 @@ public interface BeanRepository {
* found.
*/
default <T> T mandatoryFindSingleByType(Class<T> type) {
- Set<T> set = findByType(type);
- if (set.size() == 1) {
- return set.iterator().next();
- } else {
- throw new NoSuchBeanTypeException(type, set.size());
+ T answer = findSingleByType(type);
+ if (answer == null) {
+ throw new NoSuchBeanTypeException(type);
}
+ return answer;
}
/**
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
index 0cdca505fae..dd52d5a6b07 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
@@ -342,6 +342,32 @@ public class DefaultRegistry extends ServiceSupport implements Registry, LocalBe
return answer;
}
+ @Override
+ public <T> T findSingleByType(Class<T> type) {
+ T found = null;
+
+ // local repository takes precedence
+ BeanRepository local = localRepositoryEnabled ? localRepository.get() : null;
+ if (local != null) {
+ found = local.findSingleByType(type);
+ }
+
+ if (found == null && repositories != null) {
+ for (BeanRepository r : repositories) {
+ found = r.findSingleByType(type);
+ }
+ }
+
+ if (found == null) {
+ found = supplierRegistry.findSingleByType(type);
+ }
+ if (found == null) {
+ found = fallbackRegistry.findSingleByType(type);
+ }
+
+ return found;
+ }
+
@Override
protected void doStop() throws Exception {
super.doStop();
diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_2.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_2.adoc
index dca28e4a9a3..40457010611 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_2.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_2.adoc
@@ -39,8 +39,21 @@ expected to function correctly if using Java 21.
A new release of Apache Ignite is expected that will start to support Java 21.
-=== camel-spring-boot
+=== camel-spring & camel-spring-boot
+
+==== Autowiring Primary beans
+
+Camel will now take into account `@Primary` beans from Spring when autowiring by type.
+For example a JDBC `DataSource` in the SQL component will now use the `@Primary` data source
+when multiple data sources are defined.
+
+Previously Camel would not autowire if there are 2 or more beans for a given type.
+
+NOTE: This is a change in behaviour, that can affect your applications when upgrading.
+
+==== Properties
The `initialProperties` and `overrideProperties` on Camel `PropertiesComponent` will now
take precedence over Spring Boot properties. This can be used for testing purpose,
to allow overriding properties when using `CamelTestSupport` for unit testing.
+