[英]JMS and Java EE transactions
如果您在EJB容器中運行了一些Java代碼(由JMS消息傳遞啟動),並且該代碼將另一個JMS消息放入同一隊列中,那么如何阻止該消息傳遞,直到將其踢掉的代碼完成為止和它的交易已提交? 基本上,我遇到交易並發問題。 我有JMS消息A所啟動的代碼(在EJB中)。該代碼完成了一些工作,然后進行了數據庫插入(由於容器管理的EJB事務,直到所有這些代碼執行完畢,它才提交)。 然后,它放入一條消息(消息B),該消息具有剛插入隊列中的數據庫行的ID。 然后,它會在同一事務中完成一些其他工作,而這需要花費一些時間。
好吧,將帶有數據庫行ID的消息放入隊列后不久,它就被傳遞並啟動了代碼,該代碼試圖查詢由消息A所啟動的代碼插入的行。麻煩是,那插入該行的代碼仍在執行,並且其事務尚未提交。 因此,有問題的數據庫行不在要查詢的數據庫中。 結果是由於消息B錯誤而啟動的代碼無法找到所需的數據庫行。
我該如何預防? 我已經完成了有關Java EE容器中的JMS和事務的數小時研究。 我讀過的一篇教程說,您無法在同一筆交易中收到消息並發送回復。 因此,在所有事務完成之前,容器是否不應該將消息提交到隊列中?
抱歉,這個問題很亂。 我正在盡力解釋。 這里粘貼的代碼太多了。 但是環境是WildFly 8.1,可執行代碼在無狀態EJB內,JPA用於數據庫訪問,消息在隊列中,而不是主題中。 我希望有足夠的信息。
// How factory and queues are declared in java code:
@Resource(mappedName = "java:/ConnectionFactory")
ConnectionFactory connectionFactory;
@Resource(mappedName = "java:jboss/exported/jms/queue/quequeA")
Queue queueA;
@Resource(mappedName = "java:jboss/exported/jms/queue/quequeB")
Queue queueB;
//Sending message:
TextMessage message = session.createTextMessage("some message goes here");
MessageProducer producer = session.createProducer(queueA); // samething for queueB
producer.send(message);
// how queues are configured in WidlFly's standalone.conf :
<jms-queue name="quequeA">
<entry name="queue/quequeA"/>
<entry name="java:jboss/exported/jms/queue/quequeA"/> <!-- same thing for queueB -->
</jms-queue>
<address-setting match="jms.queue.quequeA">
<dead-letter-address>jms.queue.DLQ</dead-letter-address>
<redelivery-delay>5000</redelivery-delay>
<max-delivery-attempts>1</max-delivery-attempts>
<max-size-bytes>10485760</max-size-bytes>
<page-size-bytes>1048576</page-size-bytes>
<address-full-policy>PAGE</address-full-policy>
<message-counter-history-day-limit>10</message-counter-history-day-limit>
</address-setting>
// creating connection and session:
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // note: the application is running in the Java EE web/EJB environment, so both "fasle" and auto_acknowledge arguments shoudl be ignored according to the javadoc. I'm trying to use container-managed transactions for everything
我不得不更改常規連接工廠:
@Resource(mappedName = "java:/ConnectionFactory")
ConnectionFactory connectionFactory;
到XA連接工廠:
@Resource(mappedName = "java:/JmsXA")
XAConnectionFactory connectionFactory;
這使事情一開始就停止了,因為我只在@PostConstruct中為每個EJB初始化一次連接,並在帶注釋的@PreDestroy方法中將其關閉。 因此,除此之外,我還必須將連接和會話生成移到每個方法的開頭,並在每個方法的末尾將其關閉。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.