Spring Boot Atomikos Transaction Manager - PullRequest
2 голосов
/ 10 июля 2019

Я пытаюсь использовать Atomikos Transaction Manager в проекте Spring Boot для управления некоторыми транзакционными операциями, которые содержат только JMS, но не источник данных. Поэтому я настраиваю только фабрику транзакционных JMS-соединений, а не соединение с транзакционными источниками данных. Это дает следующую ошибку:

Caused by: java.lang.NoClassDefFoundError: com/atomikos/jms/AtomikosConnectionFactoryBean
    at com.tfkb.common.config.JMSConfig.xaQueueConnectionFactory(JMSConfig.java:275) ~[classes/:na]
    at ...
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_121]
    ... 67 common frames omitted

Я проверил pom.xml и в настоящее время у меня есть следующие зависимости в этом контексте:

        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-all</artifactId>
            <version>5.15.9</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atomikos</groupId>
            <artifactId>transactions-jms</artifactId>
            <version>4.0.4</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.atomikos</groupId>
            <artifactId>transactions-jta</artifactId>
            <version>4.0.4</version>
        </dependency>

Я искал, но не смог найти ничего конкретного в контексте Atomikos. Я также проверил определения и использование bean-компонентов, но все выглядит хорошо.

У меня есть эти конфигурации:

import com.atomikos.jms.AtomikosConnectionFactoryBean;
import org.apache.activemq.ActiveMQXAConnectionFactory;

@Configuration
@EnableJms
@EnableTransactionManagement
@EnableAutoConfiguration
@PropertySource(ignoreResourceNotFound = true, value = "classpath:common.properties")
public class JMSConfig implements JmsListenerConfigurer {
...
@Bean(initMethod = "init", destroyMethod = "close", name = "xaQueueConnectionFactory")
    public ConnectionFactory xaQueueConnectionFactory() {
        ActiveMQXAConnectionFactory activeMQXAConnectionFactory = new ActiveMQXAConnectionFactory();
        activeMQXAConnectionFactory.setBrokerURL(brokerURL);
        activeMQXAConnectionFactory.setUserName(userName);
        activeMQXAConnectionFactory.setPassword(password);
        AtomikosConnectionFactoryBean atomikosConnectionFactoryBean = new AtomikosConnectionFactoryBean();
        atomikosConnectionFactoryBean.setUniqueResourceName("xamq");
        atomikosConnectionFactoryBean.setLocalTransactionMode(false);
        atomikosConnectionFactoryBean.setXaConnectionFactory(activeMQXAConnectionFactory);
        return atomikosConnectionFactoryBean;
    }
package com.xxx.common.config;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import com.atomikos.jms.AtomikosConnectionFactoryBean;
import net.sf.ehcache.transaction.manager.TransactionManagerLookup;
import org.apache.activemq.ActiveMQXAConnectionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import javax.inject.Inject;
import javax.jms.ConnectionFactory;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import java.util.Properties;

@Configuration
public class AtomikosJtaConfiguration {
    @Inject
    private Environment environment ;

    public void tailorProperties(Properties properties) {
        properties.setProperty( "hibernate.transaction.manager_lookup_class",
                TransactionManagerLookup.class.getName());
    }

    @Bean
    public UserTransaction userTransaction() throws Throwable {
        UserTransactionImp userTransactionImp = new UserTransactionImp();
        userTransactionImp.setTransactionTimeout(1000);
        return userTransactionImp;
    }

    @Bean(initMethod = "init", destroyMethod = "close")
    public TransactionManager transactionManager() throws Throwable {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);
        return userTransactionManager;
    }

, а также

package com.xxx.common.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import org.springframework.transaction.jta.JtaTransactionManager;

import javax.inject.Inject;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

@Configuration
@EnableTransactionManagement
public class TxConfig {

    @Inject
    private AtomikosJtaConfiguration jtaConfiguration ;

    @Bean
    @Primary
    public PlatformTransactionManager platformTransactionManager() throws Throwable {
        UserTransaction userTransaction = jtaConfiguration.userTransaction() ;
        TransactionManager transactionManager = jtaConfiguration.transactionManager() ;
        return new JtaTransactionManager(  userTransaction, transactionManager );
    }

}

Это многомодульный проект, и я поместил эти конфигурации в общий пакет, и вызывающая сторона использует их следующим образом:

@EntityScan(basePackages = "com.servicium.entity")
@ComponentScan({"com.xxx.alarmservice.impl", "com.xxx.common",
        "com.xxx.common.interf", "com.xxx.common.config", "com.xxx.common.test"})
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
@Import({MyConfig.class, RestTemplateConfig.class, SecurityConfig.class,
        RequestLoggingConfig.class, JMSConfig.class, AtomikosJtaConfiguration.class, TxConfig.class})
public class AlarmServiceApplication {
...
}

и в этом модуле у меня есть транзакционный метод в качестве метода тестирования:

@Test
@Transactional
public void testReceiveXXX() throws Exception {
...
}
...

Может кто-нибудь помочь мне настроить Atomikos с JMS в проекте Spring Boot?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...