0

When i am trying to write an application with two database in a Spring boot, Spring Data JPA. It's not able to create databases, its given exceptions. Here is my implementation code

Application class

package com.icarat.eshiksha;
@SpringBootApplication
public class Application  extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

application.xml file

server.port=8080
server.contextPath=/Eshiksha

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db_shiksha2
spring.datasource.username=root
spring.datasource.password=*****
spring.datasource.validation-query=select 1

settings.datasource.driver-class-name=com.mysql.jdbc.Driver
settings.datasource.url=jdbc:mysql://127.0.0.1:3306/db_shiksha_settings2
settings.datasource.username=root
settings.datasource.password=*******
settings.datasource.validation-query=select 1

ShikshaDbConfig class

package com.icarat.eshiksha.config;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "shikshaEntityManagerFactory", 
        transactionManagerRef = "shikshaTransactionManager",
        basePackages = { "com.icarat.eshiksha.repository" })
public class ShikshaDbConfig {


    @Autowired
    JpaVendorAdapter jpaVendorAdapter;

    @Autowired
    DataSource dataSource;

    @Bean(name = "shikshaManager")
    public EntityManager shikshaManager() {
        return shikshaEntityManagerFactory().createEntityManager();
    }

    @Primary
    @Bean(name = "shikshaEntityManagerFactory")
    public EntityManagerFactory shikshaEntityManagerFactory() {

          Properties properties = new Properties();
            properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
            properties.setProperty("hibernate.hbm2ddl.auto","update");
            properties.setProperty("hibernate.show_sql", "false");

        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setDataSource(dataSource);
        emf.setJpaVendorAdapter(jpaVendorAdapter);
        emf.setJpaProperties(properties);
        emf.setPackagesToScan("com.icarat.eshiksha.database.entities");
        emf.setPersistenceUnitName("default");   // <- giving 'default' as name
        emf.afterPropertiesSet();
        return emf.getObject();
    }

    @Bean(name = "shikshaTransactionManager")
    public PlatformTransactionManager shikshaTransactionManager() {
        JpaTransactionManager tm = new JpaTransactionManager();
        tm.setEntityManagerFactory(shikshaEntityManagerFactory());
        return tm;
    }   
}

ShikshaSettingsDbConfig class

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "settingEntityManagerFactory", 
        transactionManagerRef = "shikshaSettingsTransactionManager",
        basePackages = { "com.icarat.eshiksha.settings.repository" })
public class ShikshaSettingsDbConfig {

     @Autowired
        JpaVendorAdapter jpaVendorAdapter;

        @Value("${settings.datasource.url}")
        private String databaseUrl;

        @Value("${settings.datasource.username}")
        private String username;

        @Value("${settings.datasource.password}")
        private String password;

        @Value("${settings.datasource.driver-class-name}")
        private String driverClassName;



        public DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource(databaseUrl, username, password);
            dataSource.setDriverClassName(driverClassName);
            return dataSource;
        }

        @Bean(name = "settingEntityManager")
        public EntityManager settingEntityManager() {
            return settingEntityManagerFactory().createEntityManager();
        }

        @Bean(name = "settingEntityManagerFactory")
        public EntityManagerFactory settingEntityManagerFactory() {
             Properties properties = new Properties();
                properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
                properties.setProperty("hibernate.hbm2ddl.auto","update");
                properties.setProperty("hibernate.show_sql", "false");
             properties.setProperty("hibernate.cache.use_second_level_cache", "true");
            properties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory");

            LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
            emf.setDataSource(dataSource());
            emf.setJpaVendorAdapter(jpaVendorAdapter);
            emf.setPackagesToScan("com.icarat.eshiksha.settings.database.entites");   // <- package for entities
            emf.setPersistenceUnitName("settingPersistenceUnit");
            emf.setJpaProperties(properties);
            emf.afterPropertiesSet();
            return emf.getObject();
        }

        @Bean(name = "settingsTransactionManager")
        public PlatformTransactionManager settingsTransactionManager() {
            return new JpaTransactionManager(settingEntityManagerFactory());
        }    
}

Organization class

@Entity
@Table(name = "Organization")
public class Organization {

    @Id
@GeneratedValue(strategy=GenerationType.AUTO)   
    @Column(name="orgId")
    private String orgId;

    @Column(name="orgName", unique=true)
    private String orgName;

    @Column(name="orgAddress")
    private String orgAddress;

    @Column(name="pincode")
    private String pincode;


    @Column(name="boardOfEducation")
    private String boardOfEducation;

    @Column(name="recognizedBy")
    private String recognizedBy;

    @Column(name="affiliationNumber")
    private String affiliationNumber;


    @Column(name="faxNumber")
    private String faxNumber;


    @Column(name = "isActive")
    private boolean isActive = true;

    @OneToOne
    private OrganizationAdmin admin;

    @OneToMany(fetch = FetchType.LAZY, mappedBy="org", cascade=CascadeType.REMOVE)
    private List<Branch> branches =new ArrayList<Branch>();
//getter //setter 
}

OrganizationDAOImpl class

package com.icarat.eshiksha.dao.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import com.icarat.eshiksha.dao.OrganizationDAO;
import com.icarat.eshiksha.database.entities.Organization;
import com.icarat.eshiksha.dto.AddOrgRequestDTO;
import com.icarat.eshiksha.repository.OrganizationRepository;
import com.icarat.eshiksha.util.StringConstants;

@Service
public class OrganizationDAOImpl implements OrganizationDAO {   

    @Autowired
    private OrganizationRepository organizationRepository;  

    @Override
    public String addOrganization(AddOrgRequestDTO request) {   
        Organization org = createHomeEntity(request);
        try {       
            organizationRepository.save(org);       
            return StringConstants.SUCCESS;
        }catch(DataIntegrityViolationException e) {     
            e.printStackTrace();                
            return null;
        } catch(Exception e) {
            e.printStackTrace();        
            return null;
        }
        }   

    private Organization createHomeEntity(final AddOrgRequestDTO request) {
        Organization home = new Organization();
        home.setOrgName(request.getOrgName());  
        home.setOrgAddress(request.getAddress());
        home.setPincode(request.getPincode());
        if(request.getFaxNumber()!=null){
        home.setFaxNumber(request.getFaxNumber());
        }
        if(request.getBoardOfEducation()!=null){
            home.setBoardOfEducation(request.getBoardOfEducation());
            }
            if(request.getRecognizedBy()!=null){
                home.setRecognizedBy(request.getRecognizedBy());
            }
            if(request.getAffiliationNumber()!=null){
                home.setAffiliationNumber(request.getAffiliationNumber());
            }
        return home;
    }

OrganizationRepository class

package com.icarat.eshiksha.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.icarat.eshiksha.database.entities.Organization;
@Repository
public interface OrganizationRepository extends JpaRepository<Organization, String>{

}

Thrown exceptions are

 2017-05-28 16:08:16.061  WARN 4424 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'organizationDAOImpl': Unsatisfied dependency expressed through field 'organizationRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'organizationRepository': Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'settingEntityManagerFactory' defined in class path resource [com/icarat/eshiksha/config/ShikshaSettingsDbConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.persistence.EntityManagerFactory]: Factory method 'settingEntityManagerFactory' threw exception; nested exception is java.lang.AbstractMethodError
2017-05-28 16:08:16.070  INFO 4424 --- [           main] utoConfigurationReportLoggingInitializer : 

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-05-28 16:08:16.075 ERROR 4424 --- [           main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'organizationDAOImpl': Unsatisfied dependency expressed through field 'organizationRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'organizationRepository': Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'settingEntityManagerFactory' defined in class path resource [com/icarat/eshiksha/config/ShikshaSettingsDbConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.persistence.EntityManagerFactory]: Factory method 'settingEntityManagerFactory' threw exception; nested exception is java.lang.AbstractMethodError
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.4.4.RELEASE.jar:1.4.4.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762) [spring-boot-1.4.4.RELEASE.jar:1.4.4.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:372) [spring-boot-1.4.4.RELEASE.jar:1.4.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-1.4.4.RELEASE.jar:1.4.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1187) [spring-boot-1.4.4.RELEASE.jar:1.4.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1176) [spring-boot-1.4.4.RELEASE.jar:1.4.4.RELEASE]
    at com.icarat.eshiksha.Application.main(Application.java:38) [classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'organizationRepository': Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'settingEntityManagerFactory' defined in class path resource [com/icarat/eshiksha/config/ShikshaSettingsDbConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.persistence.EntityManagerFactory]: Factory method 'settingEntityManagerFactory' threw exception; nested exception is java.lang.AbstractMethodError
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1531) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1276) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    ... 19 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'settingEntityManagerFactory' defined in class path resource [com/icarat/eshiksha/config/ShikshaSettingsDbConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.persistence.EntityManagerFactory]: Factory method 'settingEntityManagerFactory' threw exception; nested exception is java.lang.AbstractMethodError
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    ... 32 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'settingEntityManagerFactory' defined in class path resource [com/icarat/eshiksha/config/ShikshaSettingsDbConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.persistence.EntityManagerFactory]: Factory method 'settingEntityManagerFactory' threw exception; nested exception is java.lang.AbstractMethodError
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:519) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:508) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1189) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:261) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.getMetamodels(JpaMetamodelMappingContextFactoryBean.java:85) ~[spring-data-jpa-1.10.7.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.createInstance(JpaMetamodelMappingContextFactoryBean.java:56) ~[spring-data-jpa-1.10.7.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.createInstance(JpaMetamodelMappingContextFactoryBean.java:26) ~[spring-data-jpa-1.10.7.RELEASE.jar:na]
    at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:134) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    ... 39 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.persistence.EntityManagerFactory]: Factory method 'settingEntityManagerFactory' threw exception; nested exception is java.lang.AbstractMethodError
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    ... 57 common frames omitted
Caused by: java.lang.AbstractMethodError: null
    at org.hibernate.internal.CacheImpl.<init>(CacheImpl.java:49) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:28) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:20) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.initiateService(SessionFactoryServiceRegistryImpl.java:49) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.getService(SessionFactoryServiceRegistryImpl.java:68) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:244) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353) ~[spring-orm-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373) ~[spring-orm-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362) ~[spring-orm-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at com.icarat.eshiksha.config.ShikshaSettingsDbConfig.settingEntityManagerFactory(ShikshaSettingsDbConfig.java:71) ~[classes/:na]
    at com.icarat.eshiksha.config.ShikshaSettingsDbConfig$$EnhancerBySpringCGLIB$$1d6ef92.CGLIB$settingEntityManagerFactory$0(<generated>) ~[classes/:na]
    at com.icarat.eshiksha.config.ShikshaSettingsDbConfig$$EnhancerBySpringCGLIB$$1d6ef92$$FastClassBySpringCGLIB$$b22a78eb.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at com.icarat.eshiksha.config.ShikshaSettingsDbConfig$$EnhancerBySpringCGLIB$$1d6ef92.settingEntityManagerFactory(<generated>) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_73]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_73]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_73]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_73]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    ... 58 common frames omitted

How can i solve this problem. Please help find it out. Thank you

vishwa
  • 1
  • 1
  • 2
  • 6

1 Answers1

4

I created a working POC here. Instructions are available in the README.md. This solution builds using Gradle and uses Docker to keep two MySQL instances and a SpringBoot application exposing a REST endpoint.

Some points on your implementation:

1. Use unique bean names

You defined two configurations corresponding to your two data sources. You need to name each bean with @Bean("name") and inject them by name with @Qualifier("name").

Also one of the configurations need to have its beans annotated with @Primary else will not work, don't ask me why. Is normal to receive errors if you have multiple beans of the same type injected by type without any further qualification, but it seems that errors appear even if injection is qualified with @Qualifier("name"), where "name" is unique.

For example one of the configuration could look like:

POC MySqlSource1Config.java.

package my.java.spring.jpa.multi.repositories.config;

import my.java.spring.jpa.multi.models.Organization;
import my.java.spring.jpa.multi.repositories.source1.Source1OrganizationRepositoryImpl;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

/**
 * Repository configuration.
 * @EnableJpaRepositories to enable JPA automatic repositories.
 */
@Configuration
@EnableJpaRepositories(
        basePackageClasses = { Source1OrganizationRepositoryImpl.class },
        entityManagerFactoryRef = MySqlSource1Config.EntityManagerFactoryBeanName,
        transactionManagerRef = MySqlSource1Config.TransactionManagerBeanName
)
public class MySqlSource1Config {

    public static final String PrefixName = "source1";
    public static final String DataSourceBeanName = PrefixName + ".data-source";
    public static final String JpaVendorAdapterBeanName = PrefixName + "jpa-vendor-adapter";
    public static final String EntityManagerFactoryBeanName = PrefixName + ".entity-manager-factory";
    public static final String TransactionManagerBeanName = PrefixName + ".transaction-manager";
    public static final String RepositoryBeanName = PrefixName + ".repository";

    @Bean(TransactionManagerBeanName)
    @Primary
    public PlatformTransactionManager transactionManager(
            @Qualifier(EntityManagerFactoryBeanName) EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    @Bean(EntityManagerFactoryBeanName)
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            @Qualifier(DataSourceBeanName) DataSource dataSource,
            @Qualifier(JpaVendorAdapterBeanName) JpaVendorAdapter vendorAdapter) {

        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource);
        entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
        entityManagerFactoryBean.setJpaDialect(new HibernateJpaDialect());
        entityManagerFactoryBean.setPackagesToScan(Organization.class.getPackage().getName());
        entityManagerFactoryBean.setPersistenceUnitName("mysqlsource1");
        entityManagerFactoryBean.afterPropertiesSet();

        return entityManagerFactoryBean;
    }

    @Bean(JpaVendorAdapterBeanName)
    @Primary
    @ConfigurationProperties(prefix = "source1.mysql.jpa")
    public JpaVendorAdapter jpaVendorAdapter() {
        return new HibernateJpaVendorAdapter();
    }

    @Bean(DataSourceBeanName)
    @Primary
    @ConfigurationProperties(prefix = "source1.mysql.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
}

2. Inject beans by bean names

Because multiple bean definitions are found for the same type you should inject the beans by their name with @Qualifier():

@Bean(TransactionManagerBeanName)
@Primary
public PlatformTransactionManager transactionManager(
        @Qualifier(EntityManagerFactoryBeanName) EntityManagerFactory entityManagerFactory) {
    return new JpaTransactionManager(entityManagerFactory);
}

In contrast, the following is extracted from your code:

@Bean(name = "shikshaTransactionManager")
public PlatformTransactionManager shikshaTransactionManager() {
    JpaTransactionManager tm = new JpaTransactionManager();
    tm.setEntityManagerFactory(shikshaEntityManagerFactory());
    return tm;
}   

This is not ok, because shikshaEntityManagerFactory() will create a new instance of the EntityManagerFactory instead of injecting the existing bean.

3. No need to explicitly define EntityManager when you have EntityManagerFactory

The following is extracted from your question:

@Bean(name = "shikshaManager")
public EntityManager shikshaManager() {
    return shikshaEntityManagerFactory().createEntityManager();
}

@Primary
@Bean(name = "shikshaEntityManagerFactory")
public EntityManagerFactory shikshaEntityManagerFactory() { ... }

One point is that both are defined, another point is that, if you still need EntityManager then you should inject the EntityManagerFactory bean instead of doing a method call shikshaEntityManagerFactory() which generates another instance of the EntityManagerFactory.

4. Simplify configuration

You can use @ConfigurationProperties instead of @Value to load multiple configuration properties into your beans like:

    @Bean(JpaVendorAdapterBeanName)
    @Primary
    @ConfigurationProperties(prefix = "source1.mysql.jpa")
    public JpaVendorAdapter jpaVendorAdapter() {
        return new HibernateJpaVendorAdapter();
    }

    @Bean(DataSourceBeanName)
    @Primary
    @ConfigurationProperties(prefix = "source1.mysql.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

And then the application.yml for the two data sources will look like:

source1:
  mysql:
    jpa:
      show-sql: true
      generate-ddl: true
      database: MYSQL
    datasource:
      platform: postgres
      url: jdbc:mysql://localhost:3307/test1
      username: myuser1
      password: mypass1
      driverClassName: com.mysql.cj.jdbc.Driver
source2:
  mysql:
    jpa:
      show-sql: true
      generate-ddl: true
      database: MYSQL
    datasource:
      platform: postgres
      url: jdbc:mysql://localhost:3308/test2
      username: myuser2
      password: mypass2
      driverClassName: com.mysql.cj.jdbc.Driver

Note that jpa is loaded into JpaVendorAdapter and datasource into DataSource.

5. Keep data source repositories separate

If you need to use the same entity and repository with multiple data sources then you can keep a common interface OrganizationRepository and have separate interfaces Source1OrganizationRepository and IMPL Source1OrganizationRepositoryImpl.

On the other hand, if you have entities and repositories which are not used by the multiple data sources, (eg: Organization managed by source1 and User managed by source2) then there will be different packages managed by different sources but no need for a common interface.

This allows to name the repository bean like:

@Repository(MySqlSource1Config.RepositoryBeanName)
public interface Source1OrganizationRepository extends OrganizationRepository {
}

in order to distinguish from the other data source repository.

These are configured, like you already used them in your configurations (notice the basePackageClasses):

@Configuration
@EnableJpaRepositories(
        basePackageClasses = { Source1OrganizationRepositoryImpl.class },
        entityManagerFactoryRef = MySqlSource1Config.EntityManagerFactoryBeanName,
        transactionManagerRef = MySqlSource1Config.TransactionManagerBeanName
)
public class MySqlSource1Config { ... }

Then these repositories can be injected further, into a controller, service, or any other component, like:

@RestController
@RequestMapping("/v1/organization")
public class OrganizationController {

    private final OrganizationRepository organizationRepositoryFromSource1;
    private final OrganizationRepository organizationRepositoryFromSource2;

    @Autowired
    public OrganizationController(
            @Qualifier(MySqlSource1Config.RepositoryBeanName) OrganizationRepository organizationRepositoryFromSource1,
            @Qualifier(MySqlSource2Config.RepositoryBeanName) OrganizationRepository organizationRepositoryFromSource2) {

        this.organizationRepositoryFromSource1 = organizationRepositoryFromSource1;
        this.organizationRepositoryFromSource2 = organizationRepositoryFromSource2;
    }

...
}

Same entities can be used with multiple data sources and are loaded by the EntityManager and can be configured inside the EntityManagerFactory:

@Bean(EntityManagerFactoryBeanName)
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
        @Qualifier(DataSourceBeanName) DataSource dataSource,
        @Qualifier(JpaVendorAdapterBeanName) JpaVendorAdapter vendorAdapter) {

...
entityManagerFactoryBean.setPackagesToScan(Organization.class.getPackage().getName());
...

}

NOTE: in application.yml and application-docker.yml I used source1.mysql.jpa.generate-ddl: true. This means that the tables and schemas corresponding to the entities found by the EntityManager will be created automatically in the MySQL database. If you manage the database schema by other means, like creating scripts and migrate them using FlyWay or Liquidbase, then you might want to turn that option to false in order to adopt your own flow.

andreim
  • 3,365
  • 23
  • 21
  • Your solution doesn't work since RepositoryBeanName has no relation to datasource configurations – valijon Apr 05 '18 at 13:24