2017-04-13 87 views
1

我使用spring-boot-starter-data-jpa和spring-boot-starter-activemq製作POC。我想在jpa事務提交時在代理(activeMQ)上推送jms消息。彈簧引導xa事務數據源和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事務正在運行?

回答

2

是您的jmsTemplate事務?

jmsTemplate.setSessionTransacted(true); 

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

公共無效setSessionTransacted(布爾sessionTransacted)

設置創建JMS會話時所使用的交易模式。 默認爲「false」。請注意,在JTA事務中,參數 傳遞給創建(隊列/主題)會話(布爾事務處理,int acknowledgeMode)方法未考慮在內。根據 Java EE事務上下文,容器在 上自行決定這些值。類似地,因爲在這種情況下訪問者 在現有的JMS會話上操作,所以在本地管理的事務中這些參數不被考慮到 。

設置該標誌設定爲「真」,將使用短本地JMS事務 運行時,受管理的事務之外,並且在管理的事務(比 XA事務之外)的情況下的同步 本地JMS事務存在。這具有本地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提供了管理事務 一個JMS連接一個一個JmsTransactionManager。這允許JMS應用程序 利用Spring的管理事務功能,如第012章中的第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來創建從 連接會話時。這是因爲JMS API只有一個工廠方法,以 創建一個會話,並且它需要事務和 確認模式的值。在託管環境中,設置這些值 是環境的事務性 基礎架構的責任,因此供應商的包裝將該值忽略到JMS連接的 。在非託管 環境中使用JmsTemplate時,您可以通過使用屬性sessionTransacted和sessionAcknowledgeMode來指定這些值。當使用帶有JmsTemplate的PlatformTransactionManager的 時,模板將始終爲 提供事務性JMS會話。

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

1

哈桑給予解決。所以我將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); 
    } 

}