2016-09-21 50 views
0

如果您在EJB容器中運行一些java代碼(由JMS消息傳遞啓動),並且該代碼會將另一個JMS消息放入同一隊列,那麼如何防止消息被傳遞到啓動它的代碼已完成並且其事務已提交?基本上,我遇到了事務併發問題。我已經獲得了由JMS消息A啓動的代碼(在EJB中)。此代碼執行一些操作,然後執行數據庫插入操作(在所有代碼由於容器管理的EJB事務而執行完畢之前不會執行)。然後它將放入一條消息(消息B),該消息具有剛剛插入到隊列中的DB行的ID。然後它在同一個事務中做了一些其他的事情,需要一點時間。JMS和Java EE事務

好吧,在將帶有數據庫行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 
+0

隨着所有關於消息的討論,你確定你的意思是JMX而不是JMS? – Nicholas

+0

對不起,JMS,你是對的。 – Creature

+0

請參閱http://stackoverflow.com/questions/13890287/jms-transaction – home

回答

0

我不得不改變規則的連接工廠:

@Resource(mappedName = "java:/ConnectionFactory") 
ConnectionFactory connectionFactory; 

要XA連接工廠:

@Resource(mappedName = "java:/JmsXA") 
XAConnectionFactory connectionFactory; 

這讓事情停留在第一個工作,因爲我是初始化連接只有一次每個EJB在@PostConstruct中關閉,並在@PreDestroy註釋的方法中關閉它。所以除此之外,我必須將連接和會話生成移動到每個方法的開頭,並在每個方法結束時關閉它們。