有没有办法确保在发生异常时取消定期(每10秒)和持久定时器? @Timeout
方法的实现类似于此(从遗留代码中简化):
@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);
}
}
在doSomeBusinessLogic()
中发生任何异常时,需要回滚其事务。这工作正常。但是,我还要确保取消定时器。
直接的解决方案是将timer.cancel()
放入catch块。但是,这不起作用,因为取消也将被回滚(JEE6 Turorial):
企业bean通常在事务中创建一个计时器。如果回滚此事务,则还会回滚计时器创建。 同样,如果bean取消了回滚的事务中的计时器,则会回滚计时器取消。在这种情况下,计时器的持续时间将被重置,就好像取消从未发生过一样。
如果发生异常/回滚,如何确保取消定时器(防止进一步超时)?设置最大重试次数也是足够的,但我不认为这是JBoss支持的。
应用服务器是JBoss AS 7.2。
答案 0 :(得分:2)
将timer.cancel()放入catch块
答案 1 :(得分:2)
我也试过谢尔盖提出的解决方案,它似乎工作 - 计时器被取消。在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");
}
}
答案 2 :(得分:0)
我也有类似的情况,但是在catch子句中取消计时器似乎是可行的。我之所以需要这样做,是为了迫使容器(Wildfly)不要重试失败的超时。
代码看起来像这样:
@Timeout
public void onTimeout(Timer timer) {
try {
//the other ejb has @TransactionAttribute(TransactionAttributeType.SUPPORTS)
doSomeBusinessLogicInSomeOtherEjbThatThrowsEjbException();
} catch (EJBException e) {
timer.cancel();
throw e;//this is not necessary since the EJB context has already getRolledBack = true at this point
}
}