Spring Cloud 任务的 SimpleTaskConfiguration 和 Spring Batch 的 SimpleBatchConfiguration 防止 Spring Boot 自动

Posted

技术标签:

【中文标题】Spring Cloud 任务的 SimpleTaskConfiguration 和 Spring Batch 的 SimpleBatchConfiguration 防止 Spring Boot 自动配置 XA 事务【英文标题】:Spring cloud task's SimpleTaskConfiguration and spring batch's SimpleBatchConfiguration preventing spring boot auto configuration of XA transactions 【发布时间】:2016-11-21 13:56:46 【问题描述】:

我正在尝试为配置了 Spring Boot 的 Spring Batch/Spring Cloud 任务应用程序配置 XA/分布式事务。

我添加了以下依赖项,希望依赖于spring boot自动配置:

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

但是,以下两个类会导致配置两个事务管理器:

org.springframework.cloud.task.configuration.SimpleTaskConfiguration

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

查看以下消息:

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

然后因为配置了一个名为 transactionManagerPlatformTransactionManager,所以我的 atomikos 自动配置没有被选中:

   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)

有人可以帮我防止上述两个类对 transactionManager bean 的过度强制吗?

【问题讨论】:

您能否提供一个重现您的问题的可运行示例(build.gradle 和应用程序类)?因为,就像你之前的问题一样,没有它,我们所能做的就是把我们的猜测和假设扔给你,然后最终什么都不做。 我正在尝试组合一个示例应用程序来重现此内容。忍受我。 太棒了,谢谢,这应该很容易解决问题 这里是:github.com/balteo/atomikosIssue 唯一的要求是 Docker/Docker-compose 和 Java。 【参考方案1】:

我遇到了同样的问题,我的解决方案是实现 BatchConfigurer(保留 @EnableBatchProcessing)并手动添加 atomikos bean。

工作配置:

@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】:

看了你的例子后,我可以告诉你的是——没有办法让自动配置工作——即使你禁用了事务管理的自动配置,你确实尝试过,任务和批处理自动配置(由@EnableBatchProcessing@EnableTask 触发)仍将注册他们自己的事务管理器,从而阻止Atomikos 配置被触发。这样做的原因是因为@EnableBatchProcessing 包含BatchConfigurationSelector 配置类,而后者又包含SimpleBatchConfigurationModularBatchConfiguration,并且它们都将始终注册一个事务管理器——在任何一个bean 定义上都没有条件注释。 @EnableTask 做了一个非常相似的事情,只有SimpleTaskConfiguration

因此,我能看到的唯一解决方法是让您完全手动创建批处理和任务配置。

至于如何手动配置批处理和任务,我建议查看SimpleTaskConfiguration 和AbstractBatchConfiguration - 你可以看到所有需要注册的bean。

或者,您可以看到一个批处理示例on this Java Code Geeks page,您只需将 XML 配置转换为 Java 配置。

【讨论】:

这真的是唯一的方法吗?如果是这种情况,您能否提供有关如何创建批处理和任务配置的说明或文档指针? 是的,我在答案中添加了链接;基本上,只需参考 SimpleTaskConfiguration 和 AbstractBatchConfiguration 类,看看您需要手动定义哪些 bean。

以上是关于Spring Cloud 任务的 SimpleTaskConfiguration 和 Spring Batch 的 SimpleBatchConfiguration 防止 Spring Boot 自动的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud DataFlow 组合任务未启动

Spring Cloud Data Flow 的自定义任务中缺少参数

如何将 Spring Batch Cron 作业迁移到 Spring Cloud 任务

spring Cloud 定时任务 @Scheduled

Spring Cloud 任务的 SimpleTaskConfiguration 和 Spring Batch 的 SimpleBatchConfiguration 防止 Spring Boot 自动

spring cloud互联网分布式微服务云平台规划分析--spring cloud定时调度平台