2014-11-17 28 views
1

有什麼方法可以確保在發生異常時定期(每10秒)和持久定時器被取消?該@Timeout方法的實現是這樣的(從遺留代碼簡化):在doSomeBusinessLogic()回滾取消ejb定時器

@Timeout 
@TransactionAttribute(REQUIRES_NEW) 
public void onTimeout(Timer timer) { 
    try { 
     doSomeBusinessLogic(); 
    } catch (Exception e) { 
     // throwing this exception makes sure rollback is triggered 
     throw new EJBException(e); 
    } 
} 

在任何異常,它的事務需要被回滾。這工作正常。不過,我也會確保定時器被取消。

直接的解決方案是將timer.cancel()放在catch塊中。然而,這不起作用,因爲取消也將被回滾(JEE6 Turorial):

企業bean通常會在事務中創建一個計時器。如果此事務回滾,則定時器創建也會回滾。 同樣,如果一個bean在取消回滾的事務中取消一個定時器,定時器取消將被回滾。在這種情況下,定時器的持續時間被重置,就好像從未發生過取消一樣。

如何確保定時器在發生異常/回滾時被取消(防止進一步超時)?設置最大重試次數也是足夠的,但我認爲這不被JBoss支持。

應用程序服務器是JBoss AS 7.2。

回答

2

我也嘗試過由Sergey提出的解決方案,它似乎工作 - 定時器被取消。經過JBoss EAP 6.2測試。 這裏是我用於測試的代碼:

@Stateless 
public class TimeoutTest implements TimeoutTestLocal { 

@Resource 
TimerService timerService; 

@Resource 
SessionContext sessionContext; 

@Timeout 
@TransactionAttribute(TransactionAttributeType.NEVER) 
public void tmout(javax.ejb.Timer timer) { 
    try { 
     System.out.println("timout invoked"); 
     //instead of internal call let's invoke doNothing as 
     //this timeout callback is client of TimeoutTest EJB 
     //in this way doNothing will be run inside transaction 
     TimeoutTestLocal local = sessionContext.getBusinessObject(TimeoutTestLocal.class); 
     local.doNothing(); 
    } catch (Exception e) { 
     timer.cancel(); 
     System.out.println("Timer cancelled"); 
    } 
} 

@Override 
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
public void doNothing() { 
    throw new EJBException("RE Exception"); 
} 


@Override 
public void schedule() { 
    timerService.createTimer(5000, 10000, "test"); 
} 
} 
+0

是,該解決方案正確取消定時器,過類似的事情在我的腦海裏也是如此。但是,當應用到我的代碼中時,對應於'doNothing()'執行的內容不會回滾。這可能是因爲我的鏈接EJB調用更復雜。我同意這應該起作用。 – Magnilex

+0

你確定你的方法拋出系統異常嗎?請記住,默認情況下,應用程序異常不會回滾事務。 – slwk

+0

是的,爲了測試目的,我直接從我的代碼中拋出一個EJBException(它擴展了RuntimeException)。正如我所說,我也期待回滾,但實際上並沒有發生。話雖如此,我會說這個答案是正確的。 – Magnilex

2
  1. 您可以創建新的TRANSATION(調用next EJB)從計時器豆
  2. 你可以改變TA @TransactionAttribute(NEVER),並創建新的TRANSATION(調用next EJB)從計時器豆

而且在catch塊中放置timer.cancel()