I have two databases I need instances of at the same time, they are running on a oracle weblogic server rather than locally. In a configurator class, I have specified the sources and tested the connection and both DBs pull data properly. (When used one at a time, or with one as @Primary)
@Configuration
public class appDatabaseConfiguration {
@Bean
@Primary
public DataSource dataSourceA() throws Exception{
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
JndiTemplate corpdwJndiTemplate = new JndiTemplate();
return dataSourceLookup.getDataSource("<DBAProperties>");
}
@Bean
public DataSource dataSourceB() throws Exception{
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
JndiTemplate jndiTemplate = new JndiTemplate();
return dataSourceLookup.getDataSource("<DBBProperties>");
}
}
However, I am unable to use @Qualifier to tell the instantiation which bean in the configuration to select-
@Service
public class DaoImpl implements Dao{
@Autowired
@Qualifier("dataSourceA")
private JdbcTemplate dataSourceA;
@Autowired
@Qualifier("dataSourceB")
private JdbcTemplate dataSourceB;
public String getData() {
resultsA = dataSourceA.queryForObject("SELECT COUNT(*) FROM TABLE", String.class);
resultsB = dataSourceB.queryForObject("SELECT COUNT(*) FROM TABLE", String.class);
return resultsA resultsB;
}
}
When @Qualifier is not used: DataSourceA Query will succeed, but DataSourceB will fail (Table or View doesn't exist error)- because it is pulling the @Primary bean for both instantiations
When @Qualifier is used: Application errors with-
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type
'org.springframework.jdbc.core.JdbcTemplate' available: expected at least 1 bean which
qualifies as autowire candidate. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=dataSourceA)}
I have tried adding specific names to the bean like @Bean("dataSourceA"), @Bean(name="dataSourceB") rather than relying on the function name and several other syntax changes but no results. Does anyone have some insight here?
Note: Even when one datasource bean is commented out, and the other has only a name and not @primary it still throws the same autowire bean error, so I don't believe that the annotation is functioning properly in my project (or I'm using it wrong).
CodePudding user response:
You'll have to create two JdbcTemplates
each configured with a different datasource and autowire with the qualifier of the template, for example with
@Bean
@Primary
public JdbcTemplate jdbcTemp1(@Qualifier("dataSourceA") DataSource ds) {
return new JdbcTemplate(ds);
}
@Bean
public JdbcTemplate jdbcTemp2(@Qualifier("dataSourceB") DataSource ds) {
return new JdbcTemplate(ds);
}
...
@Autowired
@Qualifier("jdbcTemp2")
private JdbcTemplate jdbcTemplate;
CodePudding user response:
It's because the type of your beans defined in the @Configuration
is DataSource
and in your @Service
you inject beans of type JdbcTemplate
.
To make it work, you should create two more beans of type JdbcTemplate
using your two DataSource
like this :
@Configuration
public class appDatabaseConfiguration {
@Bean
@Primary
public DataSource dataSourceA() throws Exception{
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
JndiTemplate corpdwJndiTemplate = new JndiTemplate();
return dataSourceLookup.getDataSource("<DBAProperties>");
}
@Bean
public DataSource dataSourceB() throws Exception{
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
JndiTemplate jndiTemplate = new JndiTemplate();
return dataSourceLookup.getDataSource("<DBBProperties>");
}
@Bean(name="jdbcTemplateA")
public JdbcTemplate jdbcTemplateA() {
return new JdbcTemplate(dataSourceA());
}
@Bean(name="jdbcTemplateB")
public JdbcTemplate jdbcTemplateB() {
return new JdbcTemplate(dataSourceB());
}
}
And then, inject your beans using @Qualifier("jdbcTemplateA")
or @Qualifier("jdbcTemplateB")