在回滚时取消ejb计时器

问题描述 投票:1回答:3

是否有任何方法可以确保在发生异常时取消定期(每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。

java java-ee timer jboss7.x ejb-3.1
3个回答
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
投票
  1. 您可以从计时器bean创建新事务(调用下一个EJB)
  2. 您可以更改TO @TransactionAttribute(NEVER)并从计时器bean创建新事务(调用下一个EJB)

并将timer.cancel()放入catch块中


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
    }
}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.