0

I am trying to configure 2 Datasource in my spring boot batch application.

I want my batch meta-data to persist in my primary marked Datasource configuration.

The batch starts and runs normally. But when I try to save any data in my write step using Primary datasource's repository I get the following below error :

org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@1088b120] for key [HikariDataSource (HikariPool-1)] bound to thread [main]

I not able to figure out the issue here. I am providing my 2 Data source configuration classes.

My Primary Datasource configuration :

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "destinationEntityManagerFactory", transactionManagerRef = "destinationTransactionManager",basePackages = {"com.mppkvvcl.batchpoc.repository"})
@ComponentScan(basePackages = {"com.mppkvvcl.batchpoc"})
public class DestinationDatasource {

    private static final Logger logger = LoggerFactory.getLogger(DestinationDatasource.class);

    @Bean(name = "destinationDataSource")
    @Primary
    @ConfigurationProperties(prefix = "destination.datasource")
    public DataSource destinationDataSource() {
        String methodName = "dataSource() : ";
        logger.info(methodName + "called");
        logger.info(methodName + "returning destination datasource");
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "destinationEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean destinationEntityManagerFactory(
            EntityManagerFactoryBuilder builder, @Qualifier("destinationDataSource") DataSource dataSource) {
        String methodName = "destinationEntityManagerFactory() : ";
        logger.info(methodName + "called");
        return builder.dataSource(dataSource).packages("com.mppkvvcl.batchpoc").persistenceUnit("destination").build();
    }

    @Bean(name = "destinationTransactionManager")
    public PlatformTransactionManager destinationTransactionManager(@Qualifier("destinationEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        String methodName = "destinationTransactionManager() : ";
        logger.info(methodName + "called");
        return new JpaTransactionManager(entityManagerFactory);
    }
}

My Secondary Datasource configuration :

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "sourceEntityManagerFactory", transactionManagerRef = "sourceTransactionManager", basePackages = {"com.mppkvvcl.ngbdao.repositories"})
@ComponentScan(basePackages = {"com.mppkvvcl.ngbdao.daos"})
public class SourceDatasource {

    private static final Logger logger = LoggerFactory.getLogger(SourceDatasource.class);

    @Bean(name = "sourceDataSource")
    @ConfigurationProperties(prefix = "source.datasource")
    public DataSource sourceDataSource() {
        String methodName = "dataSource() : ";
        logger.info(methodName + "called");
        logger.info(methodName + "returning source datasource ");
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "sourceEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean sourceEntityManagerFactory(
            EntityManagerFactoryBuilder builder, @Qualifier("sourceDataSource") DataSource dataSource) {
        final String methodName = "sourceEntityManagerFactory() : ";
        logger.info(methodName + "called");
        return builder.dataSource(dataSource).packages("com.mppkvvcl.ngbentity.beans").persistenceUnit("source").build();
    }

    @Bean(name = "sourceTransactionManager")
    public PlatformTransactionManager sourceTransactionManager(@Qualifier("sourceEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        final String methodName = "sourceTransactionManager() : ";
        logger.info(methodName + "called");
        return new JpaTransactionManager(entityManagerFactory);
    }
}

The Exception arises only when I try to use Primary's repository for saving any data through my Primary datasource.

I am unable to debug this issue. Kindly point out the errors or wrong configurations if any.

Nitish Kumar
  • 721
  • 1
  • 10
  • 26
  • Possible duplicate of [Use of multiple DataSources in Spring Batch](https://stackoverflow.com/questions/25540502/use-of-multiple-datasources-in-spring-batch) – Mahmoud Ben Hassine Jul 23 '19 at 07:15
  • You should mark all the beans in DestinationDatasource class a Primary. Can you try that? – Gayatri Jul 23 '19 at 16:25
  • Same exception ! Even after marking all the beans in DestinationDatasource class with Primary @Julia – Nitish Kumar Jul 24 '19 at 06:37
  • There is a similar question here and some suggestions too. https://stackoverflow.com/questions/20907206/could-not-open-jpa-entitymanager-for-transaction-nested-exception-is-java-lang/21059045 – Gayatri Jul 24 '19 at 17:57

0 Answers0