spring boot xa事务数据源和jms

Bok*_*okC 2 java activemq-classic jms spring-data-jpa spring-boot

我使用 spring-boot-starter-data-jpa 和 spring-boot-starter-activemq 制作了一个 POC。我想在提交 jpa 事务时将 jms 消息推送到代理(activeMQ)上。

我的代码:UtilsateurService 具有“主要”事务:

@Service
public class UtilisateurService {

    @Autowired
    private UtilisateurRepository utilisateurRepository;

    @Autowired
    private SendMessage sendMessage;

    @Transactional(rollbackOn = java.lang.Exception.class)
    public Utilisateur create(Utilisateur utilisateur) throws Exception {
        final Utilisateur result = utilisateurRepository.save(utilisateur);
        sendMessage.send("creation utilisateur : " + result.getId());
        throw new Exception("rollback");
        //return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

SendMessage 类女巫“管理”Jms 消息:

@Component
public class SendMessage {

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Value("${jms.queue.destination}")
    private String destinationQueue;

    public void send(String msg) {
        this.jmsMessagingTemplate.convertAndSend(destinationQueue, msg);
    }

}
Run Code Online (Sandbox Code Playgroud)

我的主要课程:

@SpringBootApplication
@EnableJms
@EnableTransactionManagement
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Run Code Online (Sandbox Code Playgroud)

在抛出异常之前,JMS 消息被推送到 activeMq 代理上。所以我没有对经纪人进行“回滚”。

如何配置以运行 xa 事务?

Has*_*our 5

你的 jmsTemplate 交易了吗?

jmsTemplate.setSessionTransacted(true); 
Run Code Online (Sandbox Code Playgroud)

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/support/JmsAccessor.html#setSessionTransacted-boolean-

public void setSessionTransacted(boolean sessionTransacted)

设置创建 JMS 会话时使用的事务模式。默认值为“假”。请注意,在 JTA 事务中,不考虑传递给 create(Queue/Topic)Session(boolean transacted, intknowledgeMode) 方法的参数。根据 Java EE 事务上下文,容器对这些值做出自己的决定。类似地,在本地管理的事务中也不考虑这些参数,因为在这种情况下访问者在现有的 JMS 会话上操作。

将此标志设置为“true”将在托管事务之外运行时使用短的本地 JMS 事务,并在托管事务(XA 事务除外)存在的情况下使用同步的本地 JMS 事务。这具有与主事务(可能是本机 JDBC 事务)一起管理的本地 JMS 事务的效果,JMS 事务在主事务之后立即提交。

http://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with-and-without-xa.html

30.2.5 交易管理

Spring 提供了一个 JmsTransactionManager 来管理单个 JMS ConnectionFactory 的事务。这允许 JMS 应用程序利用 Spring 的托管事务特性,如第 17 章,事务管理中所述。JmsTransactionManager 执行本地资源事务,将来自指定 ConnectionFactory 的 JMS Connection/Session 对绑定到线程。JmsTemplate 自动检测此类事务资源并相应地对其进行操作。

在 Java EE 环境中,ConnectionFactory 将汇集连接和会话,因此这些资源可以在事务之间有效地重用。在独立环境中,使用 Spring 的 SingleConnectionFactory 将导致共享 JMS Connection,每个事务都有自己独立的 Session。或者,考虑使用特定于提供者的池适配器,例如 ActiveMQ 的 PooledConnectionFactory 类。

JmsTemplate 还可以与 JtaTransactionManager 和支持 XA 的 JMS ConnectionFactory 一起使用,以执行分布式事务。请注意,这需要使用 JTA 事务管理器以及正确配置 XA 的 ConnectionFactory!(检查您的 Java EE 服务器/JMS 提供程序的文档。)

在使用 JMS API 从连接创建会话时,在托管和非托管事务环境中重用代码可能会造成混淆。这是因为 JMS API 只有一种工厂方法来创建会话,并且它需要事务和确认模式的值。在受管环境中,设置这些值是环境事务基础结构的责任,因此供应商对 JMS 连接的包装器会忽略这些值。在非托管环境中使用 JmsTemplate 时,您可以通过使用属性 sessionTransacted 和 sessionAcknowledgeMode 来指定这些值。当使用带有 JmsTemplate 的 PlatformTransactionManager 时,模板将始终被赋予一个事务性的 JMS 会话。

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jms.html#jms-tx