I'm new to Spring's download, and I'm working on a new application that should be able to connect to one of several available databases. Based on user credentials, I determine which database to connect to, so I need the ability to dynamically change connections at runtime. I found an old Spring blog that describes a solution for here that protects the use of AbstractRoutingDataSource, which routes getConnection () calls to other DataSources based on search keys. I tried to keep a close eye on blogs, but I keep getting the following error.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in robb.referencecomponent.Application: Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException: Failed to look up JNDI DataSource with name 'dev1DataSource'; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
And here is the code for my Application.java class:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean @ConfigurationProperties(prefix="app.dev1.datasource") public DataSource dev1DataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix="app.dev2.datasource") public DataSource dev2DataSource() { return DataSourceBuilder.create().build(); } @Bean public DataSource dataSource() { return new RoutingDataSource(); } public class RoutingDataSource extends AbstractRoutingDataSource { public RoutingDataSource() { super(); Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DbLocation.DEV1, "dev1DataSource"); targetDataSources.put(DbLocation.DEV2, "dev2DataSource"); setTargetDataSources(targetDataSources); setDefaultTargetDataSource(DbLocation.DEV2); } @Override protected Object determineCurrentLookupKey() { return ClientContextHolder.getDbLocation(); } } }
And I set the DataSource configuration in the properties file as follows:
app.dev1.datasource.url=jdbc:oracle:thin:@dev1_db_url app.dev1.datasource.username=dev1 app.dev1.datasource.password=XXXXXXX app.dev1.datasource.driver-class-name=oracle.jdbc.OracleDriver app.dev2.datasource.url=jdbc:oracle:thin:@dev2_db_url app.dev2.datasource.username=dev2 app.dev2.datasource.password=XXXXXXX app.dev2.datasource.driver-class-name=oracle.jdbc.OracleDriver
I called one of my dev1DataSource DataSources' and he complains that he cannot find it using JNDI, but when I remove the class RoutingDataSource and define dataSource () bean and make dev1DataSource () bean @Primary I can connect to the dev1 database . I'm not sure what I did wrong by porting this old blog code to my application, I know that beans were configured in the examples using xml, but mine were configured with Java code and annotations, maybe some errors were made in this translation?
Does anyone have any experience with AbstractRoutingDataSource in Spring boot and have they encountered such problems?