spring boot xa transaction datasource和jms

时间:2017-04-13 12:48:24

标签: java spring-boot jms activemq spring-data-jpa

我使用spring-boot-starter-data-jpa和spring-boot-starter-activemq创建一个POC。当提交jpa事务时,我想在代理(activeMQ)上推送jms消息。

我的代码: UtilsateurService有" main"事务:

@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;
    }
}

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

}

我的主要课程:

@SpringBootApplication
@EnableJms
@EnableTransactionManagement
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

在抛出异常之前,JMS消息是在activeMq代理上推送的。所以我没有"回滚"在经纪人身上。

如何配置让xa事务运行?

2 个答案:

答案 0 :(得分:2)

是你的jmsTemplate Transacted?

jmsTemplate.setSessionTransacted(true); 

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

  

public void setSessionTransacted(boolean sessionTransacted)

     

设置创建JMS会话时使用的事务模式。   默认为" false"。请注意,在JTA事务中,参数   传递给create(Queue / Topic)Session(boolean transacted,int   acknowledgeMode)方法没有考虑在内。取决于   Java EE事务上下文,容器做出自己的决定   这些价值观。类似地,不考虑这些参数   在本地管理的事务中,自访问者以来   在这种情况下,它在现有的JMS会话上运行。

     

将此标记设置为" true"将使用简短的本地JMS事务   在托管事务之外运行时,同步   在托管交易的情况下的本地JMS交易(除了   XA交易)存在。这具有本地JMS的效果   交易与主要交易一起管理(可能   是一个本机JDBC事务),提交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执行   本地资源事务,绑定JMS连接/会话对   从指定的ConnectionFactory到线程。 JmsTemplate的   自动检测此类事务资源并进行操作   他们因此。

     

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

     

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

     

在托管和非托管事务环境中重用代码   使用JMS API从a创建会话时可能会造成混淆   连接。这是因为JMS API只有一个工厂方法   创建一个Session,它需要事务的值和   确认模式。在托管环境中,设置这些值   是环境交易的责任   基础架构,因此供应商的包装器会忽略这些值   JMS连接。在非托管中使用JmsTemplate时   环境你可以通过使用指定这些值   属性sessionTransacted和sessionAcknowledgeMode。使用时   使用JmsTemplate的PlatformTransactionManager,模板将永远   获得一个事务性JMS会话。

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

答案 1 :(得分:1)

Hassen给出了解决方案。所以我将SendMessage类更改为:

@Component
public class SendMessage {

    private final JmsMessagingTemplate jmsMessagingTemplate;

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

    @Autowired
    public SendMessage(JmsMessagingTemplate jmsMessagingTemplate) {
        this.jmsMessagingTemplate = jmsMessagingTemplate;
        this.jmsMessagingTemplate.getJmsTemplate().setSessionTransacted(true);
    }

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

}