Распределенная транзакция между удаленными службами REST, реализованная с помощью Spring Boot с использованием диспетчера транзакций Atomikos

Мне нужны две службы REST, которые являются частью одной транзакции (распределенной транзакции), поэтому, если, например, клиент вызывает SERVICE_1, который был успешным, а затем SERVICE_2, который не был успешным, SERVICE_2 И SERVICE_1 должен выполнить откат.

Я успешно добился этого с помощью диспетчера транзакций Atomikos (TransactionEssentials), служб, реализованных с помощью Apache CXF, и клиента Java (оркестратор транзакций), который вызывает службы REST с помощью JAX-RS. Я основывал свою работу на отличных примерах, предоставленных Atomikos, которые можно найти здесь: https://www.atomikos.com/downloads/extreme-transactions/com/atomikos/examples/5.0.6/examples-5.0.6-project.zip (примеры-jta-rest-jaxrs).

Проблема, с которой я столкнулся, заключается в том, что когда я заменяю реализацию служб REST на Spring Boot, глобальная транзакция больше не работает. Я сузил проблему до службы 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.

Ниже приведены некоторые важные фрагменты кода.

Клиент / звонящий

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();
    }
}

Я нашел расплывчатую информацию о том, что при весенней загрузке вы должны использовать Atomikos ExtremeTransaction вместо TransactionEssentials, но я не уверен, что это решение.


person zoran    schedule 05.02.2020    source источник


Ответы (1)


Ты используешь

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

классы?

TransactionAwareRestClientFilter находится в пакете jaxrs.

person Ursache    schedule 20.02.2020
comment
Я пробовал использовать эти классы, но, насколько я могу судить, последняя версия Spring использует версию 4.0.6 Atomikos, и эти классы отсутствуют в этой версии. Они доступны в com.atomikos transaction-remoting 5.0.6, а этой библиотеки нет в 4.0.6. Я так и не понял, как использовать атомикос 5.0.6 с последней версией Spring. Возможно ли, что это доступно только в TransactionsExptreme (платная версия)? Какие-либо предложения? - person zoran; 26.02.2020
comment
@zoran, если вы используете весеннюю загрузку, то вы, вероятно, также используете BOM (выравнивание версий). Вы используете maven или gradle в качестве системы сборки? Попробуйте эти ресурсы: Maven: baeldung.com/spring-boot-dependency- management-custom-parent Gradle: docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/ Попробуйте переопределить управляемые версии. - person Ursache; 27.02.2020