2014-04-28 86 views
1

我正在使用JMS執行一些長時間運行的導入過程,但遇到一些重複的消息問題,我不太明白。爲什麼JMS傳遞消息兩次?

流程如下。一些支持bean代碼發送消息給消息Bean。消息bean收到此消息,輪詢第三方服務,然後如果有新數據要導入,則將這些行提交到數據庫中。問題是JMS在我的導入過程需要一段時間(大約60秒左右)的情況下發送了兩次消息。如果沒有要導入的新行並且該過程需要30秒左右,則該消息只發送一次。

我認爲這與確認收到消息有關,所以我做的第一件事情(因爲自動確認沒有工作)將QueueSession設置爲Session.CLIENT_ACKNOWLEDGE,並將msg.acknowledge()放入我的onMessage方法。可悲的是,這些消息仍然被髮送兩次。

在此期間沒有發生錯誤代碼或異常。

這是代碼。

在支持bean

public MyBackingBean(){ 
    try { 
     InitialContext ctx = new InitialContext(); 
     qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY); 
     qcon = qconFactory.createQueueConnection(); 
     qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); 

     queue = (javax.jms.Queue) ctx.lookup(IMPORT_QUEUE); 
     qsender = qsession.createSender(queue); 
     qsender.setDeliveryMode(DeliveryMode.NON_PERSISTENT); 

     qcon.start(); 

    } catch (JMSException e) { 
     System.out.println(e); 
    } catch (NamingException e) { 
     System.out.println(e); 
    } 

public void startImport() { 
     try { 
      // send a JMS message for the long running job 
      MapMessage mapMessage = qsession.createMapMessage(); 
      mapMessage.setObjectProperty("ipAddress", "127.0.0.1"); 
      qsender.send(mapMessage); 
     } catch (JMSException e) { 
      e.printStackTrace(); 
     } catch (Throwable te) { 
      te.printStackTrace(); 
     } 
} 

在導入短信豆

@Override 
public void onMessage(Message msg) { 
    try { 
      // create an ADF Application Module 
      // poll a third party for some data 
      // copy these rows (if new) and then 
      // commit via the ADF Application Module 
     } 
    catch (Exception e){ 
     // no errors are being thrown 
    } 
} 

現在,我通過檢查郵件是否是交還忽略重複(msg.getJMSRedelivered() )和無視重複,但我對創可貼不太滿意。

有沒有人有這方面的一些指針?

回答

1

請問,我不能確定發生了什麼,但是意識到,使用AUTO_ACKNOWLEDGE,直到線程從onMessage()調用返回時,確認纔會真正發生。因此,如果您在onMessage()調用中花費了60秒,那麼對於重新傳送我並不感到驚訝。 使用CLIENT_ACKNOWLEDGE,通過調用msg.acknowledge(),您應該明確確認該消息。但是,你在做什麼?在onMessage()中花費60秒後?那麼你會得到同樣的行爲,我期望。 只要您輸入onMessage()調用,您就可以調用msg.acknowledge(),但意識到這意味着如果onMessage()方法後面的某些內容崩潰,則不會重新傳遞消息。但是看起來你並沒有使用持續交付,所以也許你不在乎。

這裏有一個很好的參考;

http://www2.sys-con.com/itsg/virtualcd/Java/archives/0604/chappell/index.html#s1