3

I am trying to get Atomikos to work with my Spring Boot/Spring Batch application.

Here is are the relevant portions of my code:

Datasource config:

@Configuration
public class DatasourceConfiguration extends AbstractCloudConfig {

    @Bean
    @Qualifier("batch_database")
    public DataSource batchDatasource() {
        return connectionFactory().dataSource("batch_database");
    }

    @Bean
    public PlatformTransactionManager transactionManager(){
        return  new JtaTransactionManager();
    }

    @Bean
    public TaskConfigurer configurer(){
        return new DefaultTaskConfigurer(batchDatasource());
    }
}

Atomikos auto-config dependency:

compile("org.springframework.boot:spring-boot-starter-jta-atomikos")

My application.properties:

spring.datasource.application.driver-class-name=org.postgresql.xa.PGXADataSource
spring.datasource.batch.driver-class-name=org.postgresql.xa.PGXADataSource

Here is the auto-configuration report:

   DataSourceTransactionManagerAutoConfiguration matched
      - @ConditionalOnClass classes found: org.springframework.jdbc.core.JdbcTemplate,org.springframework.transaction.PlatformTransactionManager (OnClassCondition)

   DataSourceTransactionManagerAutoConfiguration.DataSourceTransactionManagerConfiguration matched
      - @ConditionalOnBean (types: javax.sql.DataSource; SearchStrategy: all) found the following [batchDatasource, applicationDatasource, batch_database, application_database, database] (OnBeanCondition)

   AtomikosJtaConfiguration did not match
      - @ConditionalOnClass classes found: org.springframework.transaction.jta.JtaTransactionManager,com.atomikos.icatch.jta.UserTransactionManager (OnClassCondition)
      - @ConditionalOnMissingBean (types: org.springframework.transaction.PlatformTransactionManager; SearchStrategy: all) found the following [transactionManager] (OnBeanCondition)

   AtomikosJtaConfiguration.AtomikosJtaJmsConfiguration did not match
      - required @ConditionalOnClass classes not found: javax.jms.Message (OnClassCondition)
      - Ancestor 'org.springframework.boot.autoconfigure.transaction.jta.AtomikosJtaConfiguration' did not match (ConditionEvaluationReport.AncestorsMatchedCondition)

I am not sure why Atomikos is not auto-configured... Can anyone please help?

edit: I have commented out the JTA transactionManager bean and I now get the following auto-configuration report:

   DataSourceTransactionManagerAutoConfiguration matched
      - @ConditionalOnClass classes found: org.springframework.jdbc.core.JdbcTemplate,org.springframework.transaction.PlatformTransactionManager (OnClassCondition)

    DataSourceTransactionManagerAutoConfiguration.DataSourceTransactionManagerConfiguration matched
          - @ConditionalOnBean (types: javax.sql.DataSource; SearchStrategy: all) found the following [batchDatasource, applicationDatasource, batch_database, application_database, database] (OnBeanCondition)

   TransactionAutoConfiguration matched
      - @ConditionalOnClass classes found: org.springframework.transaction.support.TransactionTemplate,org.springframework.transaction.PlatformTransactionManager (OnClassCondition)
      - @ConditionalOnSingleCandidate (types: org.springframework.transaction.PlatformTransactionManager; SearchStrategy: all) found a primary candidate amongst the following [transactionManager] (OnBeanCondition)

   AtomikosJtaConfiguration did not match
      - @ConditionalOnClass classes found: org.springframework.transaction.jta.JtaTransactionManager,com.atomikos.icatch.jta.UserTransactionManager (OnClassCondition)
      - @ConditionalOnMissingBean (types: org.springframework.transaction.PlatformTransactionManager; SearchStrategy: all) found the following [transactionManager] (OnBeanCondition)

   AtomikosJtaConfiguration.AtomikosJtaJmsConfiguration did not match
      - required @ConditionalOnClass classes not found: javax.jms.Message (OnClassCondition)
      - Ancestor 'org.springframework.boot.autoconfigure.transaction.jta.AtomikosJtaConfiguration' did not match (ConditionEvaluationReport.AncestorsMatchedCondition)

How can I make sure the Atomikos transaction manager is picked up?

edit 2: I have excluded TransactionManager classes as follows:

@EnableAutoConfiguration(exclude = {DataSourceTransactionManagerAutoConfiguration.class, TransactionAutoConfiguration.class})

but I seems that SimpleBatchConfiguration and SimpleTaskConfiguration still force one of several TransactionManager class(es) on me:

2016-07-12 11:27:57.846  INFO 4851 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'transactionManager' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration; factoryMethodName=transactionManager; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.cloud.task.configuration.SimpleTaskConfiguration; factoryMethodName=transactionManager; initMethodName=null; destroyMethodName=(inferred); defined in org.springframework.cloud.task.configuration.SimpleTaskConfiguration]

causing the AtomikosJtaConfiguration not to match...

Can someone please advise a best practice in order to get Atomikos auto-configuration to work?

balteo
  • 23,602
  • 63
  • 219
  • 412
  • 2
    Because you are adding your own `JtaTransactionManager` that disables the auto configuration. – M. Deinum Jul 12 '16 at 08:46
  • @M.Deinum: thanks. I have commented out the jta transaction manager but somehow a local transaction manager is picked up by spring boot... – balteo Jul 12 '16 at 09:04
  • I guess it is a slightly different question but how can I figure out where this `transactionManager` bean mentioned in the auto-configuration report comes from? – balteo Jul 12 '16 at 09:13
  • That is a different question, but that is answered in the report `DataSourceTransactionManagerAutoConfiguration matched` says it all. – M. Deinum Jul 12 '16 at 09:23
  • Take a look at: http://stackoverflow.com/questions/37821028/spring-boot-integration-with-spring-batch-and-jpa . I feel that this could be a similar 'type' of issue, maybe my answer in linked thread will give you some lead. – patrykos91 Jul 14 '16 at 14:05
  • I am still not sure how to sort my original issue - which is actually a Spring Boot auto-configuration problem due to my current setup... Can anyone please help? – balteo Jul 18 '16 at 19:18
  • Hi, have you found a way to resolved this issue? – rhorvath Aug 25 '16 at 08:07

1 Answers1

0

You don't need to add Atomikos or Bitronix to specify a PlatformTransactionManager for your datasource. See Entities not persisting. Are RepositoryItemWriter & SimpleJpaWriter thread-safe?.

Community
  • 1
  • 1
delewis
  • 131
  • 1
  • 8
  • Hi delewis. According to this post: http://stackoverflow.com/questions/26820818, it seems the only way to have the job repository data and the application data in two different databases is to use XA/distributed transactions. – balteo Jul 14 '16 at 11:50
  • I am therefore not sure the persisting issue is related to thread safety. – balteo Jul 14 '16 at 11:57
  • My application has two data sources, as well, that read and write between each other as part of a batch job. Even though the post is referencing thread safety, the issue that I had with entities not persisting is similar to your's, and adding a PlatformTransactionManager to my data source and step beans addressed the issue. – delewis Jul 14 '16 at 18:14
  • I have a requirement for two databases (not just datasources).Do you think I can avoid distributed transactions ? – balteo Jul 14 '16 at 19:21
  • I have two databases, as well. My application does not utilize XA datasource, but I did find that entities would not persist unless I created a JpaTransactionManager like this (targetDataSource is my 1st database that I am reading from): @Bean public PlatformTransactionManager platformTransactionManager(@Qualifier("targetDataSource") DataSource targetDataSource) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setDataSource(targetDataSource); return transactionManager; } – delewis Jul 14 '16 at 20:55
  • Then, [this answer](http://stackoverflow.com/a/26882092/536299) - which states that one needs XA transactions in order to write to two different databases - might be incorrect? – balteo Jul 14 '16 at 21:32
  • 1
    You could use a form of [chained transaction manager](https://github.com/spring-projects/spring-data-commons/blob/master/src/main/java/org/springframework/data/transaction/ChainedTransactionManager.java) but XA is the only way you can guarantee that either both writes succeed or they both fail, no matter what. You can also refer to [this article](http://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with-and-without-xa.html) - granted, it's old - but it still holds, not much has changed since then. – Miloš Milivojević Jul 16 '16 at 10:44