![](/img/trans.png)
[英]Atomikos transaction issue with JMS listener and Oracle datasource - XID raised -4: the supplied XID is invalid for this XA resource
[英]spring boot xa transaction datasource and jms
我使用spring-boot-starter-data-jpa和spring-boot-starter-activemq创建了一个POC。 我想在提交jpa事务时在代理(activeMQ)上推送jms消息。
我的代码: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;
}
}
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事务运行?
是你的jmsTemplate交易?
jmsTemplate.setSessionTransacted(true);
public void setSessionTransacted(boolean sessionTransacted)
设置创建JMS会话时使用的事务模式。 默认为“false”。 请注意,在JTA事务中,不考虑传递给create(Queue / Topic)Session(boolean transacted,int acknowledgeMode)方法的参数。 根据Java EE事务上下文,容器会自行决定这些值。 类似地,在本地管理的事务中也不考虑这些参数,因为在这种情况下访问者在现有的JMS会话上操作。
将此标志设置为“true”将在托管事务外部运行时使用短本地JMS事务,并且在托管事务(XA事务除外)存在时使用同步本地JMS事务。 这具有本地JMS事务与主事务(可能是本机JDBC事务)一起管理的效果,JMS事务在主事务之后立即提交。
30.2.5交易管理
Spring提供了一个JmsTransactionManager来管理单个JMS ConnectionFactory的事务。 这允许JMS应用程序利用Spring的托管事务功能,如第17章“事务管理”中所述。 JmsTransactionManager执行本地资源事务,将JMS连接/会话对从指定的ConnectionFactory绑定到线程。 JmsTemplate会自动检测此类事务资源并对其进行相应操作。
在Java EE环境中,ConnectionFactory将池连接和会话,因此这些资源可以跨事务有效地重用。 在独立环境中,使用Spring的SingleConnectionFactory将导致共享JMS连接,每个事务都有自己独立的Session。 或者,考虑使用特定于提供者的池适配器,例如ActiveMQ的PooledConnectionFactory类。
JmsTemplate还可以与JtaTransactionManager和支持XA的JMS ConnectionFactory一起使用,以执行分布式事务。 请注意,这需要使用JTA事务管理器以及正确配置XA的ConnectionFactory! (查看Java EE服务器的/ JMS提供程序的文档。)
使用JMS API从Connection创建会话时,在托管和非托管事务环境中重用代码可能会造成混淆。 这是因为JMS API只有一个工厂方法来创建会话,它需要事务和确认模式的值。 在托管环境中,设置这些值是环境的事务基础结构的责任,因此供应商的JMS连接包装器会忽略这些值。 在非托管环境中使用JmsTemplate时,可以通过使用属性sessionTransacted和sessionAcknowledgeMode来指定这些值。 将PlatformTransactionManager与JmsTemplate一起使用时,将始终为模板提供事务性JMS会话。
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jms.html#jms-tx
哈森给出了解决方案。 所以我将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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.