We have two databases in our Spring Boot Application called source and target. Here is the configuration for those
Source Configuration
package com.alex.myapp.config;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "sourceManagerFactory",
transactionManagerRef = "sourceTransactionManager",
basePackages = {"com.alex.myapp.source.repository"}
)
public class SourceDbConfiguration {
@Autowired
private Environment env;
@Primary
@Bean(name = "sourceManagerFactory")
public LocalContainerEntityManagerFactoryBean
sourceManagerFactory(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean em = builder
.dataSource(sourceDataSource())
.packages("com.alex.myapp.source.entity")
.persistenceUnit("source")
.build();
return em;
}
@Primary
@Bean
public DataSource sourceDataSource() {
DriverManagerDataSource dataSource
= new DriverManagerDataSource();
dataSource.setDriverClassName(
env.getProperty("spring.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty("spring.datasource.username"));
dataSource.setPassword(env.getProperty("spring.datasource.password"));
return dataSource;
}
@Primary
@Bean(name = "sourceTransactionManager")
public PlatformTransactionManager sourceTransactionManager(
@Qualifier("sourceManagerFactory") EntityManagerFactory
sourceManagerFactory
) {
return new JpaTransactionManager(sourceManagerFactory);
}
}
Target Configuration
package com.alex.myapp.config;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "targetManagerFactory",
transactionManagerRef = "targetTransactionManager",
basePackages = {"com.alex.myapp.target.repository"}
)
public class TargetDbConfiguration {
@Autowired
private Environment env;
@Primary
@Bean(name = "targetManagerFactory")
public LocalContainerEntityManagerFactoryBean
targetManagerFactory(EntityManagerFactoryBuilder builder) {
LocalContainerEntityManagerFactoryBean em = builder
.dataSource(targetDataSource())
.packages("com.alex.myapp.target.entity")
.persistenceUnit("target")
.build();
return em;
}
@Primary
@Bean
public DataSource targetDataSource() {
DriverManagerDataSource dataSource
= new DriverManagerDataSource();
dataSource.setDriverClassName(
env.getProperty("target.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("target.datasource.url"));
dataSource.setUsername(env.getProperty("target.datasource.username"));
dataSource.setPassword(env.getProperty("target.datasource.password"));
return dataSource;
}
@Bean(name = "targetTransactionManager")
public PlatformTransactionManager targetTransactionManager(
@Qualifier("targetManagerFactory") EntityManagerFactory
targetManagerFactory) {
return new JpaTransactionManager(targetManagerFactory);
}
}
When I try to start server it throws below mentioned error
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-09-19 13:30:53 - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sourceManagerFactory' defined in class path resource [com/alex/myapp/config/SourceDbConfiguration.class]: Unsatisfied dependency expressed through method 'sourceManagerFactory' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:732)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:474)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1247)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1096)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1089)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:859)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
Jut in case if I comment out target configuration's class level annotation everything works fine. It seems both Database Configurations are conflicting with each other.