Spring cloud task SimpleTaskConfiguration and Spring batch support SimpleBatchConfiguration Spring automatic configuration of transaction loading XA

I am trying to configure XA / distributed transactions for a spring batch / spring cloud task application configured with spring boot.

I added the following dependency, hoping to rely on the automatic spring boot configuration:

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

However, the following two classes cause the configuration of two transaction managers:

  • org.springframework.cloud.task.configuration.SimpleTaskConfiguration

  • org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration

See the following message:

 2016-07-18 21:46:19.952 INFO 18995 --- [ main] osbfsDefaultListableBeanFactory : 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] 

and then when a PlatformTransactionManager named transactionManager is configured, my automatic atomikos configuration is not raised:

  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) 

Can someone help me prevent this excessive forcing transactionManager beans caused by the two classes above?

+6
source share
2 answers

I had the same problem and my solution was to implement BatchConfigurer (supporting @EnableBatchProcessing) and add atomikos beans manually.

JobConfig:

 @Configuration @EnableBatchProcessing public class JobConfig implements BatchConfigurer { @Autowired private DataSource dataSource; @Autowired private JtaTransactionManager jtaTransactionManager; // ... skipping some code @Override public JobRepository getJobRepository() throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(dataSource); factory.setTransactionManager(jtaTransactionManager); return factory.getObject(); } @Override public PlatformTransactionManager getTransactionManager() throws Exception { return jtaTransactionManager; } @Override public JobLauncher getJobLauncher() throws Exception { SimpleJobLauncher launcher = new SimpleJobLauncher(); launcher.setJobRepository(getJobRepository()); launcher.setTaskExecutor(new SimpleAsyncTaskExecutor()); return launcher; } @Override public JobExplorer getJobExplorer() throws Exception { JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean(); jobExplorerFactoryBean.setDataSource(dataSource); jobExplorerFactoryBean.afterPropertiesSet(); return jobExplorerFactoryBean.getObject(); } 

AtomikosConfig:

 @Configuration public class AtomikosConfig extends AbstractJtaPlatform { @Bean(initMethod = "init", destroyMethod = "close") @DependsOn("atomikosUserTransactionService") public UserTransactionManager atomikosTransactionManager() { UserTransactionManager manager = new UserTransactionManager(); manager.setForceShutdown(false); manager.setStartupTransactionService(false); return manager; } @Bean(initMethod = "init", destroyMethod = "shutdownForce") public UserTransactionServiceImp atomikosUserTransactionService() { Properties properties = new Properties(); return new UserTransactionServiceImp(properties); } @Bean public UserTransactionImp atomikosUserTransaction() throws SystemException { UserTransactionImp transaction = new UserTransactionImp(); transaction.setTransactionTimeout(300); return transaction; } @Primary @Bean public JtaTransactionManager jtaTransactionManager() throws Exception { JtaTransactionManager manager = new JtaTransactionManager(); manager.setTransactionManager(atomikosTransactionManager()); manager.setUserTransaction(atomikosUserTransaction()); manager.setAllowCustomIsolationLevels(true); return manager; } @Bean public ActiveMQXAConnectionFactory xaFactory() { ActiveMQXAConnectionFactory factory = new ActiveMQXAConnectionFactory(); factory.setBrokerURL("tcp://localhost:61616"); factory.setUserName("admin"); factory.setPassword("admin"); //factory.setTrustAllPackages(true); factory.setTransactedIndividualAck(true); return factory; } @Bean(initMethod = "init", destroyMethod = "close") public AtomikosConnectionFactoryBean connectionFactory() { AtomikosConnectionFactoryBean factoryBean = new AtomikosConnectionFactoryBean(); factoryBean.setUniqueResourceName("amq1"); factoryBean.setXaConnectionFactory(xaFactory()); factoryBean.setMaxPoolSize(10); return factoryBean; } @Bean public AtomikosJtaPlatform springJtaPlatformAdapter() throws Exception { AtomikosJtaPlatform platform = new AtomikosJtaPlatform(); platform.setJtaTransactionManager(jtaTransactionManager()); platform.setTransactionManager(atomikosTransactionManager()); platform.setUserTransaction(atomikosUserTransaction()); return platform; } @Override protected TransactionManager locateTransactionManager() { return atomikosTransactionManager(); } @Override protected UserTransaction locateUserTransaction() { return atomikosTransactionManager(); } 
+2
source

Looking at your example, I can tell you that there is no way to perform automatic configuration - even if you turn off the automatic configuration for transaction management in which you tried, the task and automatic batch setup (called by @EnableBatchProcessing and @EnableTask ) will register their own transaction managers and thus do not run Atomikos Configuration. The reason for this is that @EnableBatchProcessing includes a BatchConfigurationSelector configuration class, which in turn includes a SimpleBatchConfiguration or ModularBatchConfiguration , and both will always register a transaction manager - no conditional annotations on any of the bean definitions. @EnableTask does a very similar thing, only with SimpleTaskConfiguration .

Thus, the only way out of this that I see is to create a batch and task configuration completely manually.

Regarding how to manually configure the package and tasks, I would recommend looking at SimpleTaskConfiguration and AbstractBatchConfiguration - you can see there all the beans that you will need to register.

Alternatively, you can see the batch example on this Java Geeks page , you just need to translate the XML configuration into the Java configuration.

+1
source

All Articles