【问题标题】:Distributed transaction across remote REST services implemented with Spring Boot using Atomikos trasaction manager使用 Atomikos 事务管理器通过 Spring Boot 实现跨远程 REST 服务的分布式事务
【发布时间】:2020-05-21 21:42:17
【问题描述】:

我需要两个属于单个事务(分布式事务)的 REST 服务,因此,例如,如果客户端调用成功的 SERVICE_1,然后调用不成功的 SERVICE_2,则 SERVICE_2 AND SERVICE_1 必须执行回滚。

我通过 Atomikos 事务管理器 (TransactionEssentials)、使用 Apache CXF 实现的服务以及使用 JAX-RS 调用 REST 服务的 Java 客户端(事务协调器)成功地实现了这一点。我的工作基于 Atomikos 提供的出色示例,可在此处找到:https://www.atomikos.com/downloads/extreme-transactions/com/atomikos/examples/5.0.6/examples-5.0.6-project.zip (examples-jta-rest-jaxrs)。

我面临的问题是,当我用 Spring Boot 替换 REST 服务实现时,全局事务不再起作用。我将问题缩小到 Spring Boot REST 服务,该服务不返回调用者所需的标头中的“Atomikos-Extent”属性(开始并提交全局事务)。这是调用者抛出的异常:

WARNING: Invalid extent found - any remote work will time out and rollback.
java.lang.IllegalArgumentException: Expected an extent but found none. The remote work will not be committed by us.
      at com.atomikos.remoting.DefaultExportingTransactionManager.addExtent(DefaultExportingTransactionManager.java:70)

那么,问题来了,如何实现 Spring Boot REST 服务,使其可以通过 Atomikos 事务管理器参与全局事务。

下面是一些可能很重要的代码 sn-ps。

客户/呼叫者

Client client1= newClient().register(JacksonJsonProvider.class)
        .register(ParticipantsProvider.class)
        .register(TransactionAwareRestClientFilter.class);
Client client2 = //same as client1
UserTransactionManager utm = new UserTransactionManager();
utm.init();
utm.begin();
callService1();
callService2();
utm.commit();
utm.close();

服务

@EnableTransactionManagement
@SpringBootApplication
public class SpringBootAtomikosExampleApplication {
    //..    
    @Bean(initMethod="init", destroyMethod="close")
    public AtomikosDataSourceBean dataSource() {
        AtomikosDataSourceBean ds = new AtomikosDataSourceBean();   
        //..
        return ds;
    }
}

@Transactional
@RestController
public class MyController {

    @RequestMapping("/test")
    public void test() throws Exception {   
        TransactionManager tm = new UserTransactionManager();
        tm.begin();
        try (Connection con = dataSource.getConnection();
            Statement s = con.createStatement();) {
            s.executeQuery("select count(*) from menu");
        }
        tm.commit();
    }
}

我发现模糊的信息表明,使用 spring boot 你应该使用 Atomikos ExtremeTransaction 而不是 TransactionEssentials,但我不确定这是否是解决方案。

【问题讨论】:

    标签: rest spring-boot jta distributed-transactions atomikos


    【解决方案1】:

    你在用吗

    • com.atomikos.remoting.spring.rest.TransactionAwareRestContainerFilter
    • com.atomikos.remoting.spring.rest.TransactionAwareRestClientInterceptor

    上课?

    TransactionAwareRestClientFilter 在 jaxrs 包下。

    【讨论】:

    • 我尝试使用这些类,但据我所知,最新版本的 Spring 使用的是 Atomikos 的 4.0.6 版本,而这些类在该版本中不存在。它们在 com.atomikos transactions-remoting 5.0.6 中可用,而这个库在 4.0.6 中不存在。我不知道如何在最新版本的 spring 中使用 atomikos 5.0.6。它是否可能仅在 TransactionsExptreme(付费版)中可用?有什么建议吗?
    • @zoran 如果您使用的是 spring boot,那么您可能也在使用 BOM(版本对齐)。您使用 maven 或 gradle 作为构建系统吗?试试这个资源: Maven:baeldung.com/spring-boot-dependency-management-custom-parent Gradle:docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/… 尝试覆盖托管版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 2023-03-22
    • 2017-05-29
    • 2015-04-22
    • 2011-09-08
    相关资源
    最近更新 更多