我使用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事务运行?
答案 0 :(得分:2)
是你的jmsTemplate Transacted?
jmsTemplate.setSessionTransacted(true);
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事务 在主要交易之后。
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);
}
}