This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new f275b466ced Primary spring (#11842) f275b466ced is described below commit f275b466ced60c3863139988f84a2dbe2a6ec39b Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Oct 26 14:47:34 2023 +0200 Primary spring (#11842) * CAMEL-20042: camel-spring - findSingleByType should favour @Primary beans from Spring * Bump threshold for test * CAMEL-20042: camel-spring - Autowire @Primary beans supported * CAMEL-20042: camel-spring - Autowire @Primary beans supported * CAMEL-20042: camel-sql - Stored component should use autowired datasource like sql do. * CAMEL-20042: camel-spring - Autowire @Primary beans supported * CAMEL-20042: camel-spring - Autowire @Primary beans supported --- .../camel/catalog/components/sql-stored.json | 2 +- .../TransactedStackSizeBreakOnExceptionTest.java | 2 +- .../org/apache/camel/spring/primary/Customer.java | 23 ++++++ .../apache/camel/spring/primary/CustomerImpl.java | 31 ++++++++ .../camel/spring/primary/FindSingleByTypeTest.java | 90 ++++++++++++++++++++++ .../org/apache/camel/spring/primary/MyService.java | 36 +++++++++ .../apache/camel/spring/primary/findBySingle.xml | 38 +++++++++ .../spi/ApplicationContextBeanRepository.java | 13 ++++ .../sql/stored/SqlStoredComponentConfigurer.java | 5 ++ .../camel/component/sql/stored/sql-stored.json | 2 +- .../component/sql/stored/SqlStoredComponent.java | 45 ++++------- .../component/sql/stored/SqlStoredEndpoint.java | 4 + .../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 +++- 15 files changed, 304 insertions(+), 37 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql-stored.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql-stored.json index 109ff9de0e7..db619b0c73b 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql-stored.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql-stored.json @@ -22,7 +22,7 @@ "lenientProperties": false }, "componentProperties": { - "dataSource": { "index": 0, "kind": "property", "displayName": "Data Source", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "javax.sql.DataSource", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the DataSource to use to communicate with the database." }, + "dataSource": { "index": 0, "kind": "property", "displayName": "Data Source", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "javax.sql.DataSource", "deprecated": false, "autowired": true, "secret": false, "description": "Sets the DataSource to use to communicate with the database." }, "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...] "autowiredEnabled": { "index": 2, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] }, diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/TransactedStackSizeBreakOnExceptionTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/TransactedStackSizeBreakOnExceptionTest.java index b1a6de28a69..11149462fd3 100644 --- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/TransactedStackSizeBreakOnExceptionTest.java +++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/TransactedStackSizeBreakOnExceptionTest.java @@ -27,7 +27,7 @@ public class TransactedStackSizeBreakOnExceptionTest extends TransactionClientDa private static final boolean PRINT_STACK_TRACE = false; private int total = 100; - private int failAt = 75; + private int failAt = 80; @Test public void testStackSize() throws Exception { 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..e570c05bd7a --- /dev/null +++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/primary/FindSingleByTypeTest.java @@ -0,0 +1,90 @@ +/* + * 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 java.util.Set; + +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 testFindByType() { + // should find primary + Set<Customer> set = context.getRegistry().findByType(Customer.class); + + // should find both beans + Assertions.assertEquals(2, set.size()); + } + + @Test + public void testFindSingleMandatory() { + // should find primary + Customer c = context.getRegistry().mandatoryFindSingleByType(Customer.class); + Assertions.assertEquals("Donald", c.name()); + + // should not find anything + Assertions.assertThrows(NoSuchBeanTypeException.class, + () -> context.getRegistry().mandatoryFindSingleByType(UuidGenerator.class)); + } + +} 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 95be7e1fcd9..fb1e2a2ee25 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 @@ -25,6 +25,7 @@ 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.config.NamedBeanHolder; import org.springframework.context.ApplicationContext; /** @@ -83,4 +84,16 @@ public class ApplicationContextBeanRepository implements BeanRepository { return BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, type); } + @Override + public <T> T findSingleByType(Class<T> type) { + try { + // this API allows to support @Primary beans that should take precedence in + // case there are 2+ beans of the same type. + NamedBeanHolder<T> holder = applicationContext.getAutowireCapableBeanFactory().resolveNamedBean(type); + return holder.getBeanInstance(); + } catch (NoSuchBeanDefinitionException e) { + return null; + } + } + } diff --git a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredComponentConfigurer.java b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredComponentConfigurer.java index e5eda080e46..87140ea58b5 100644 --- a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredComponentConfigurer.java +++ b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredComponentConfigurer.java @@ -31,6 +31,11 @@ public class SqlStoredComponentConfigurer extends PropertyConfigurerSupport impl } } + @Override + public String[] getAutowiredNames() { + return new String[]{"dataSource"}; + } + @Override public Class<?> getOptionType(String name, boolean ignoreCase) { switch (ignoreCase ? name.toLowerCase() : name) { diff --git a/components/camel-sql/src/generated/resources/org/apache/camel/component/sql/stored/sql-stored.json b/components/camel-sql/src/generated/resources/org/apache/camel/component/sql/stored/sql-stored.json index 109ff9de0e7..db619b0c73b 100644 --- a/components/camel-sql/src/generated/resources/org/apache/camel/component/sql/stored/sql-stored.json +++ b/components/camel-sql/src/generated/resources/org/apache/camel/component/sql/stored/sql-stored.json @@ -22,7 +22,7 @@ "lenientProperties": false }, "componentProperties": { - "dataSource": { "index": 0, "kind": "property", "displayName": "Data Source", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "javax.sql.DataSource", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the DataSource to use to communicate with the database." }, + "dataSource": { "index": 0, "kind": "property", "displayName": "Data Source", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "javax.sql.DataSource", "deprecated": false, "autowired": true, "secret": false, "description": "Sets the DataSource to use to communicate with the database." }, "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...] "autowiredEnabled": { "index": 2, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] }, diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java index 20754ab017b..1a4f329c8d8 100644 --- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java +++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java @@ -17,7 +17,6 @@ package org.apache.camel.component.sql.stored; import java.util.Map; -import java.util.Set; import javax.sql.DataSource; @@ -36,45 +35,35 @@ public class SqlStoredComponent extends DefaultComponent { private static final Logger LOG = LoggerFactory.getLogger(SqlStoredComponent.class); - @Metadata + @Metadata(autowired = true) private DataSource dataSource; @Override protected Endpoint createEndpoint(String uri, String template, Map<String, Object> parameters) throws Exception { - DataSource target = null; - // endpoint options overrule component configured datasource - DataSource ds = resolveAndRemoveReferenceParameter(parameters, "dataSource", DataSource.class); - if (ds != null) { - target = ds; - } - if (target == null) { - // fallback and use component - target = dataSource; - } - if (target == null) { - // check if the registry contains a single instance of DataSource - Set<DataSource> dataSources = getCamelContext().getRegistry().findByType(DataSource.class); - if (dataSources.size() > 1) { - throw new IllegalArgumentException( - "Multiple DataSources found in the registry and no explicit configuration provided"); - } else if (dataSources.size() == 1) { - target = dataSources.iterator().next(); - } + SqlStoredEndpoint endpoint = new SqlStoredEndpoint(uri, this); + endpoint.setTemplate(template); + setProperties(endpoint, parameters); + + // endpoint configured data source takes precedence + DataSource ds = dataSource; + if (endpoint.getDataSource() != null) { + ds = endpoint.getDataSource(); } - if (target == null) { + if (ds == null) { throw new IllegalArgumentException("DataSource must be configured"); } - LOG.trace("Using DataSource: {}", target); - - JdbcTemplate jdbcTemplate = new JdbcTemplate(target); + // create template + JdbcTemplate jdbcTemplate = new JdbcTemplate(ds); Map<String, Object> templateOptions = PropertiesHelper.extractProperties(parameters, "template."); PropertyBindingSupport.bindProperties(getCamelContext(), jdbcTemplate, templateOptions); - SqlStoredEndpoint endpoint = new SqlStoredEndpoint(uri, this, jdbcTemplate); - endpoint.setTemplate(template); - setProperties(endpoint, parameters); + // set template on endpoint + endpoint.setJdbcTemplate(jdbcTemplate); + endpoint.setDataSource(ds); + endpoint.setTemplateOptions(templateOptions); + return endpoint; } diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java index 1f4c345042d..0f9b3622eb9 100644 --- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java +++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java @@ -64,6 +64,10 @@ public class SqlStoredEndpoint extends DefaultEndpoint { description = "Configures the Spring JdbcTemplate with the key/values from the Map") private Map<String, Object> templateOptions; + public SqlStoredEndpoint(String uri, SqlStoredComponent component) { + super(uri, component); + } + public SqlStoredEndpoint(String uri, SqlStoredComponent component, JdbcTemplate jdbcTemplate) { super(uri, component); setJdbcTemplate(jdbcTemplate); 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. +