8

I wanted to connect my spring boot app to 2 databases . So according to a tutorial i created 2 config classes.

Config Class 1

@Configuration @EnableTransactionManagement @PropertySource({ "classpath:database-configs.properties" }) @EnableJpaRepositories( basePackages = {"com.dialog.pod.ideabiz_admin.data_access_objects"}, entityManagerFactoryRef = "adminEntityManagerFactory", transactionManagerRef = "adminTransactionManager") public class IdeabizAdminConfig { @Autowired private Environment env; @Bean PlatformTransactionManager adminTransactionManager() { return new JpaTransactionManager(adminEntityManagerFactory().getObject()); } @Bean LocalContainerEntityManagerFactoryBean adminEntityManagerFactory() { HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter(); // jpaVendorAdapter.setGenerateDdl(true); LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); factoryBean.setDataSource(adminDataSource()); factoryBean.setJpaVendorAdapter(jpaVendorAdapter); factoryBean.setPackagesToScan("com.dialog.pod.ideabiz_admin.models"); factoryBean.setJpaPropertyMap(jpaProperties()); factoryBean.setPersistenceUnitName("adminDataSource"); return factoryBean; } @Bean DataSource adminDataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getProperty("admin.jdbc.driverClassName")); dataSource.setUrl(env.getProperty("admin.jdbc.url")); dataSource.setUsername(env.getProperty("admin.jdbc.username")); dataSource.setPassword(env.getProperty("admin.jdbc.password")); return dataSource; } private Map<String, Object> jpaProperties() { Map<String, Object> props = new HashMap<>(); props.put("hibernate.implicit_naming_strategy","org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl"); props.put("hibernate.physical_naming_strategy","com.dialog.pod.PhysicalNamingStrategyImpl"); return props; } } 

Config Class 2

@Configuration @EnableTransactionManagement @PropertySource({ "classpath:database-configs.properties" }) @EnableJpaRepositories( basePackages = {"com.dialog.pod.ideabiz_log_summary.data_access_objects"}, entityManagerFactoryRef = "sumLogEntityManagerFactory", transactionManagerRef = "sumLogTransactionManager") public class IdeabizLogSummaryConfig { @Autowired private Environment env; @Bean PlatformTransactionManager sumLogTransactionManager() { return new JpaTransactionManager(sumLogEntityManagerFactory().getObject()); } @Bean LocalContainerEntityManagerFactoryBean sumLogEntityManagerFactory() { HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter(); // jpaVendorAdapter.setGenerateDdl(true); LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); factoryBean.setDataSource(adminDataSource()); factoryBean.setJpaVendorAdapter(jpaVendorAdapter); factoryBean.setPackagesToScan("com.dialog.pod.ideabiz_log_summary.models"); factoryBean.setJpaPropertyMap(jpaProperties()); factoryBean.setPersistenceUnitName("sumLogDataSource"); return factoryBean; } @Bean DataSource adminDataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getProperty("sumlog.jdbc.driverClassName")); dataSource.setUrl(env.getProperty("sumlog.jdbc.url")); dataSource.setUsername(env.getProperty("sumlog.jdbc.username")); dataSource.setPassword(env.getProperty("sumlog.jdbc.password")); return dataSource; } private Map<String, Object> jpaProperties() { Map<String, Object> props = new HashMap<>(); props.put("hibernate.implicit_naming_strategy","org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl"); props.put("hibernate.physical_naming_strategy","com.dialog.pod.PhysicalNamingStrategyImpl"); return props; } } 

Application Class

@SpringBootApplication @EnableAutoConfiguration (exclude = { DataSourceAutoConfiguration.class }) @Configuration @ComponentScan public class PodApiApplication { public static void main(String[] args) { SpringApplication.run(PodApiApplication.class, args); } @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/").allowedOrigins("*"); } }; } } 

When i try to run the app i get following error.

*************************** APPLICATION FAILED TO START *************************** Description: Method requestMappingHandlerMapping in org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration required a single bean, but 2 were found: - adminEntityManagerFactory: defined by method 'adminEntityManagerFactory' in class path resource [com/dialog/pod/ideabiz_admin/IdeabizAdminConfig.class] - sumLogEntityManagerFactory: defined by method 'sumLogEntityManagerFactory' in class path resource [com/dialog/pod/ideabiz_log_summary/IdeabizLogSummaryConfig.class] Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed Process finished with exit code 1 

I put @Primary to the first config class(according to another tutorial). When i do that datasource in the first config class works. Problem is when i do this first datasource also applied to all the jparepositories.

I'm new to Spring boot. I have been trying to solve this problem for over 5 hours :( . Thanks in advance for any help you are able to provide.

Full Log

2017-01-27 00:52:39.713 INFO 6704 --- [ main] com.dialog.pod.PodApiApplication : Starting PodApiApplication on DESKTOP-4B89ITN with PID 6704 (started by y2ksh in H:\Spring MVC Workspace\platform-overview-dashboard\PODApi) 2017-01-27 00:52:39.718 INFO 6704 --- [ main] com.dialog.pod.PodApiApplication : No active profile set, falling back to default profiles: default 2017-01-27 00:52:39.938 INFO 6704 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6e171cd7: startup date [Fri Jan 27 00:52:39 IST 2017]; root of context hierarchy 2017-01-27 00:52:41.712 INFO 6704 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'adminDataSource' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=ideabizAdminConfig; factoryMethodName=adminDataSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/dialog/pod/ideabiz_admin/IdeabizAdminConfig.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=ideabizLogSummaryConfig; factoryMethodName=adminDataSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/dialog/pod/ideabiz_log_summary/IdeabizLogSummaryConfig.class]] 2017-01-27 00:52:42.804 INFO 6704 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [class org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$3cc0fc3] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2017-01-27 00:52:43.594 INFO 6704 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8081 (http) 2017-01-27 00:52:43.609 INFO 6704 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat 2017-01-27 00:52:43.609 INFO 6704 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.6 2017-01-27 00:52:43.810 INFO 6704 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2017-01-27 00:52:43.810 INFO 6704 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3891 ms 2017-01-27 00:52:44.247 INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] 2017-01-27 00:52:44.253 INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricFilter' to: [/*] 2017-01-27 00:52:44.254 INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] 2017-01-27 00:52:44.254 INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] 2017-01-27 00:52:44.254 INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] 2017-01-27 00:52:44.254 INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] 2017-01-27 00:52:44.255 INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*] 2017-01-27 00:52:44.255 INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*] 2017-01-27 00:52:44.367 INFO 6704 --- [ main] o.s.j.d.DriverManagerDataSource : Loaded JDBC driver: com.mysql.jdbc.Driver 2017-01-27 00:52:44.403 INFO 6704 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'adminDataSource' 2017-01-27 00:52:44.435 INFO 6704 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ name: adminDataSource ...] 2017-01-27 00:52:44.634 INFO 6704 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.11.Final} 2017-01-27 00:52:44.636 INFO 6704 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found 2017-01-27 00:52:44.641 INFO 6704 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist 2017-01-27 00:52:44.725 INFO 6704 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} 2017-01-27 00:52:45.302 INFO 6704 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect 2017-01-27 00:52:46.178 INFO 6704 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'adminDataSource' 2017-01-27 00:52:46.189 INFO 6704 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'sumLogDataSource' 2017-01-27 00:52:46.190 INFO 6704 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ name: sumLogDataSource ...] 2017-01-27 00:52:46.228 INFO 6704 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect 2017-01-27 00:52:46.291 INFO 6704 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'sumLogDataSource' 2017-01-27 00:52:46.695 INFO 6704 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory 2017-01-27 00:52:46.947 INFO 6704 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory 2017-01-27 00:52:47.496 INFO 6704 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6e171cd7: startup date [Fri Jan 27 00:52:39 IST 2017]; root of context hierarchy 2017-01-27 00:52:47.560 WARN 6704 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]: Factory method 'requestMappingHandlerMapping' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'openEntityManagerInViewInterceptor' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration$JpaWebConfiguration$JpaWebMvcConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available: expected single matching bean but found 2: adminEntityManagerFactory,sumLogEntityManagerFactory 2017-01-27 00:52:47.562 INFO 6704 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'sumLogDataSource' 2017-01-27 00:52:47.563 INFO 6704 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'adminDataSource' 2017-01-27 00:52:47.566 INFO 6704 --- [ main] o.apache.catalina.core.StandardService : Stopping service Tomcat 2017-01-27 00:52:47.586 INFO 6704 --- [ main] utoConfigurationReportLoggingInitializer : Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. 2017-01-27 00:52:47.592 ERROR 6704 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPLICATION FAILED TO START *************************** Description: Method requestMappingHandlerMapping in org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration required a single bean, but 2 were found: - adminEntityManagerFactory: defined by method 'adminEntityManagerFactory' in class path resource [com/dialog/pod/ideabiz_admin/IdeabizAdminConfig.class] - sumLogEntityManagerFactory: defined by method 'sumLogEntityManagerFactory' in class path resource [com/dialog/pod/ideabiz_log_summary/IdeabizLogSummaryConfig.class] Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed Process finished with exit code 1 
4
  • Can you update your question with the version of the code that contains the @Primary annotations? (You will need to use that.) Commented Jan 26, 2017 at 20:05
  • @gyoder do you mean spring boot version? 1.4 Commented Jan 26, 2017 at 20:09
  • no, the configuration class with the @Primary attribute(s) which then cause the same datasource to be applied to all repos Commented Jan 26, 2017 at 20:11
  • @gyoder config class 1 Commented Jan 26, 2017 at 20:14

3 Answers 3

7

Mark one of the beans as primary

 @Primary @Bean public EntityManagerFactory entityManagerFactory() { } 
Sign up to request clarification or add additional context in comments.

1 Comment

This is not a great solution because it assumes that one of the data sources can semantically be deemed "primary".
7

Your Spring Boot application implicitly activates Spring Web Mvc via WebMvcAutoConfiguration which is triggered by having, among others, Servlet.class in your class path. This WebMvcAutoConfiguration requires a bean of type EntityManagerFactory. However, you have registered two such beans adminEntityManagerFactory and sumLogEntityManagerFactory. So you have to tell Spring Web Mvc which is your preferred one via @Primary on top of the respective @Bean method. Alternatively if you don't need Web Mvc autoconfiguration switch it off by @EnableAutoConfiguration(exclude={WebMvcAutoConfiguration}) and configure Web Mvc manually.

2 Comments

Your explanation is great, could be better if it's nicely formatted.
@jumping_monkey I edited the response for formatting
1

It turns out i used same method name for both datasource beans . This was the reason why only one data source used for all jparepos. Thanks @Javatar81 for explaining how bean naming works

1 Comment

Name should not make a difference because the default name of a bean is given by the method's name. This time you've used @Primary correctly and this is why it works. Could you please check whether it still works without name attribute defined?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.