2012-01-06 101 views
4

我有以下消息驅動Bean:馬克交易爲只回滾的消息驅動Bean不重試消息

@MessageDriven(mappedName = "jms/...", activationConfig = { 
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), 
    @ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryAttempts", propertyValue = "5"), 
    @ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryInterval", propertyValue = "1000") 
}) 
public class MyMessageListener implements MessageListener { 

    @Resource 
    private MessageDrivenContext context; 

    @Override 
    @TransactionAttribute(REQUIRED) 
    public void onMessage(Message message) {    
    } 
} 

裏面的onMessage方法,我做了一些處理,其在這裏並不重要。在某些情況下,我想放棄處理。在這種情況下,我想將事務標記爲僅回滾,並且不想重試處理。

至少在Glassfish 3.1.1上,如果我在MessageDrivenContext上調用context.setRollbackOnly(),並且結束處理而不拋出異常,則會以非常非常短的時間間隔無限次地重新發送消息。所以這對我來說是沒有選擇的。

如果我拋出一個RuntimeException該消息被重新傳遞,因爲我已經指定它。它以1秒的間隔重新發送5次。但就我而言,我根本不想重試處理。

如果我只是在不拋出任何異常的情況下結束處理,並且沒有調用context.setRollbackOnly(),則交易將按照預期提交。但是我需要回滾事務,因爲我可能已經更改了一些JPA實體。

我的問題是:如何將事務標記爲僅回滾而不觸發郵件重新傳遞?

+0

如果拋出一個'RuntimeException'並且配置爲根本不重新傳遞? – DagR 2012-01-07 01:00:10

+0

因爲我也有我想重試處理的情況。這也是爲什麼a明確指定重試參數的原因。 – 2012-01-07 14:16:50

回答

1

我看到兩個選項:

  1. 標註與@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)豆,使用Bean管理的事務和沒有AUTO_ACKNOWLEDGE(MDB中明確承認消息)。如果您的MDB是更大的XA交易的一部分,則不是一種選擇,您將不會有機會影響全局交易結果。
  2. 檢查消息上的getJMSRedelivered()標誌,並簡單地丟棄重新發送的消息。這裏的麻煩是,在重新交付時,您不知道是否應該忽略重新交付(您在某些情況下表示您想重試處理)—您必須臨時(在數據庫或緩存中)存儲ID的處理失敗的消息,所以你知道你是否可以安全地忽略它們。