2011-05-12 51 views
1

使用Spring-JMS,可以通過DefaultMessageListenerContainer在外部事務上下文中接收消息。使用TransactionManager使用Spring JmsTemplate編寫消息

然而唯一記載的方式來寫一個消息是通過JmsTemplate.send(…),我看不出這可怎麼強制使用給定TransactionManager

任何人都可以指向正確的方向嗎?


更多信息:確保一個事務管理器可用(WebSphereUowTransactionManager),在使用JmsTemplate.write針對Oracle AQjmsFactory.getQueueConnectionFactory(dataSource)結果:

org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during JMS processing; nested exception is oracle.jms.AQjmsException: could not use local transaction commit in a global transaction 
    at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:316) 
    at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:168) 
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:469) 
    at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:534) 
Caused by: oracle.jms.AQjmsException: could not use local transaction commit in a global transaction 
    at oracle.jms.AQjmsSession.commitNoCheck(AQjmsSession.java:1053) 
    at oracle.jms.AQjmsSession.commit(AQjmsSession.java:1021) 
    at org.springframework.jms.support.JmsUtils.commitIfNecessary(JmsUtils.java:217) 
    at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:573) 
    at org.springframework.jms.core.JmsTemplate$3.doInJms(JmsTemplate.java:536) 
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:466) 
    ... 24 more 
Caused by: java.sql.SQLException: could not use local transaction commit in a global transaction 
    at oracle.jdbc.driver.PhysicalConnection.disallowGlobalTxnMode(PhysicalConnection.java:6647) 
    at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:3635) 
    at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:3680) 
    at oracle.jdbc.OracleConnectionWrapper.commit(OracleConnectionWrapper.java:133) 
    at oracle.jms.AQjmsSession.commitNoCheck(AQjmsSession.java:1049) 
    ... 29 more 

因此,雖然我沒有理由懷疑下面的提醒,我無法測試它,因爲我無法弄清楚如何讓AQ JMS不嘗試提交。隨着我學習更多,將會更新。

回答

7

我的理解是,JMS生產者固有通過JTA處理。通過通過JMS MessageProducer發送消息,使用線程本地JTA事務(如果存在的話)。

這是在由Spring手冊(section 21.2.5)暗示:

JmsTemplate也可以與JtaTransactionManager和XA-能夠JMS ConnectionFactory用於執行分佈式事務中使用。請注意,這需要使用JTA事務管理器以及正確配置XA的ConnectionFactory

設置創建JMS會話時所使用的交易模式:

這也由JmsAccessor.setSessionTransacted(的JmsTemplate超類)(javadoc)建議。默認值是「false」。 請注意,在JTA事務中,傳遞給create(Queue/Topic)Session(boolean transacted, int acknowledgeMode)方法的參數未被考慮在內。根據J2EE事務上下文,容器根據這些值做出自己的決定。類似地,在本地管理的事務中也不會考慮這些參數,因爲在這種情況下訪問者在現有的JMS會話上操作。

將此標誌設置爲「true」將在託管事務外運行時使用短本地JMS事務,並且在託管事務(除XA事務外)的情況下使用同步本地JMS事務。後者具有與主事務(可能是本地JDBC事務)一起管理的本地JMS事務的作用,JMS事務在主事務之後立即提交。

因此,通過啓動一個JTA事務(即通過使用Spring的事務API與JtaTransactionManager)並調用JmsTemplate.send(...),你會被髮送綁定到該交易的消息。

+0

謝謝。我想知道,當另一個非Spring過程啓動時,Spring是否能夠找到正在運行的事務?我明天會發現... – Synesso 2011-05-12 07:34:20

+1

@Synesso:是的,會的。JTA事務由容器管理,而不是由Spring管理。 – skaffman 2011-05-12 07:38:37

相關問題