2017-05-17 28 views
0

我使用Spring Integration從JMS讀取消息,處理它們,然後使用我自己的dbPersistor的persist方法將其持久化到數據庫,該方法返回void類型。我編寫了一個測試用例來驗證發佈到JMS的消息是否成功保存在數據庫中。我的SI和JMS配置都作爲本次測試如下 - 在測試中,我做了以下Spring集成:從JMS讀取 - >處理消息 - >堅持在DB

<int:poller fixed-delay="500" default="true"/> 

<int:channel id="inputChannel"> 
    <int:queue/> 
</int:channel> 
<int:channel id="errorChannel"> 
    <int:queue/> 
</int:channel> 
<jms:message-driven-channel-adapter id="jmsInboudAdapter"   
    connection-factory="connectionFactory" destination-name="MessageQueue" 
    channel="inputChannel" error-channel="errorChannel" transaction-manager="dbTxManager"          
    acknowledge="transacted"/> 

<int:chain id="handlerChain" input-channel="inputChannel"> 
    <int:service-activator ref="jmsMessageHandler" method="handleMessage" /> 
    <int:service-activator ref="dbPersistor" method="persist" /> 
</int:chain> 

然後 -

  • jmsTemplate.send()
  • verifyMessageWasPersistedToDB

這當我只向數據庫發佈一條消息時效果很好。但是,當我通過jmsTemplate.send()循環發佈多條消息時,主線程完成操作,同時SI線程仍在執行,並嘗試驗證數據庫中的消息,並失敗,因爲某些消息尚未保存。我的問題是 -

  1. 如何使主線程等待SI線程完成,然後調用驗證方法?
  2. 如果出現db異常和回滾,我如何驗證失敗的消息是否回到原始隊列中?

由於 AJ

回答

0
  1. inputChannel不應該是一個隊列通道 - 時被插入到隊列中的消息中的JMS事務將提交 - 數據庫交易不會在的範圍來執行JMS事務。你必須使用直接渠道(刪除輪詢和<queue/>)。見the documentation on transactions in Spring Integration

  2. 您將不得不查詢結果的數據庫;你可能會添加一個攔截器和一些CountDownLatch,但只需要輪詢數據庫,直到結果出現或者一段時間結束爲止。

+0

謝謝Gary,將'inputChannel'改爲'DirectChannel'幫助我解決了事務管理問題。現在失敗的消息停留在後端消息存儲中。 但我的第一個問題仍然存在 - 我如何讓主線程在繼續執行其餘代碼之前等待SI鏈完成執行?目前,我在調用主線程中的其餘代碼之前使用了一個'Thread.sleep()'。 –

+0

正如我在#2中所說的,您不能「輕鬆」地讓測試線程等待 - 您必須將其他組件添加到流程中。直到預期結果顯示(或者某個時間限制到期,表示測試失敗),繼續輪詢數據庫會更容易。 –

+0

我明白你的觀點。我將採用在流中添加CountDownLatch的方法。感謝所有的答覆和解釋加里! –