I am developing a Spring Boot based application in which I would like to create 2 beans: One will point to 'Oracle' database; the other will point to Hive. I've declared them as follows:
public @Bean
BoneCPDataSource metadataDataSource() {
BoneCPDataSource boneCPDataSource = new BoneCPDataSource();
boneCPDataSource.setDriverClass(getDriver());
boneCPDataSource.setJdbcUrl(getJdbcUrl());
boneCPDataSource.setUser(getUser());
boneCPDataSource.setPassword(getPassword());
boneCPDataSource.setMaxConnectionsPerPartition(5);
boneCPDataSource.setPartitionCount(5);
return boneCPDataSource;
}
public @Bean
BasicDataSource hiveDataSource() {
BasicDataSource basicDataSource = new BasicDataSource();
// Note: In a separate command window, use port forwarding like this:
//
// ssh -L 127.0.0.1:9996:<server>:<port> -l <userid> <server>
//
// and then login as the generic user.
basicDataSource.setDriverClassName("org.apache.hadoop.hive.jdbc.HiveDriver");
basicDataSource.setUrl("jdbc:hive://127.0.0.1:9996:10000/mytable");
return basicDataSource;
}
Problem is at the startup I am getting this:
Exception in thread "main"
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name
'org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration':
Injection of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private javax.sql.DataSource
org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration.dataSource;
nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
qualifying bean of type [javax.sql.DataSource] is defined: expected
single matching bean but found 2: metadataDataSource,hiveDataSource
Mainly because both of them inherit from javax.sql.DataSource. What's the best way to fix this?
EDIT:
Now I've declared them as follows:
public @Bean (name="metadataDataSource")
BoneCPDataSource metadataDataSource() {
BoneCPDataSource boneCPDataSource = new BoneCPDataSource();
boneCPDataSource.setDriverClass(getDriver());
boneCPDataSource.setJdbcUrl(getJdbcUrl());
boneCPDataSource.setUser(getUser());
boneCPDataSource.setPassword(getPassword());
boneCPDataSource.setMaxConnectionsPerPartition(5);
boneCPDataSource.setPartitionCount(5);
return boneCPDataSource;
}
public @Bean (name="hiveDataSource")
BasicDataSource hiveDataSource() {
BasicDataSource basicDataSource = new BasicDataSource();
// Note: In a separate command window, use port forwarding like this:
//
// ssh -L 127.0.0.1:9996:<server>:<port> -l <userid> <server>
//
// and then login as the generic user.
basicDataSource.setDriverClassName("org.apache.hadoop.hive.jdbc.HiveDriver");
basicDataSource.setUrl("jdbc:hive://127.0.0.1:9996:10000/mytable");
return basicDataSource;
}
And got this exception:
Exception in thread "main"
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name
'org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration':
Injection of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private javax.sql.DataSource
org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration.dataSource;
nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
qualifying bean of type [javax.sql.DataSource] is defined: expected
single matching bean but found 2: metadataDataSource,hiveDataSource
The other classes are referring to these beans as follows:
public class MetadataProcessorImpl implements MetadataProcessor {
@Autowired
@Qualifier("metadataDataSource")
BoneCPDataSource metadataDataSource;
@Controller public class HiveController {
@Autowired
@Qualifier("hiveDataSource")
BasicDataSource hiveDataSource;
Can I define spring bean twice with same name in different bean definition file? Yes. When the second bean definition file loads, it overrides the definition from the first file. The main objective of this behavior is to ovrrride the previously loaded bean definition.
The limitation of this approach is that we need to manually instantiate beans using the new keyword in a typical Java-based configuration style. Therefore, if the number of beans of the same class increases, we need to register them first and create beans in the configuration class.
Spring Couldn't autowired,there is more than one bean of `` type. Bookmark this question.
Spring beans are identified by their names within an ApplicationContext. Thus, bean overriding is a default behavior that happens when we define a bean within an ApplicationContext which has the same name as another bean. It works by simply replacing the former bean in case of a name conflict.
Set one of the beam as @Primary as described in the section 67.2 Configure Two DataSources
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-two-datasources
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With