我在JBoss 6.4上部署了一个EJB计时器。在99%的情况下,计时器工作正常,但有时需要花费一点时间才能完成并抛出PersistenceException: Transaction was rolled back in a different thread!
。
我发现这是由于transacion超时值太低。我不想编辑默认值,而是覆盖特定于方法的超时。为了解决这个问题,我将功能分为两个方法:一个用@Timeout
注释的方法和一个实际完成工作的方法。
这是我的计时器实现:
@Singleton
public class MyTimer implements SomeTimerInterface {
@EJB
private SomeManager myManager;
@Resource
private TimerService timerService;
private Timer timer;
@Override
public void startTimer() {
// Timer scheduled to fire every 7th minute
ScheduleExpression schedule = new ScheduleExpression();
schedule = schedule.hour("*").minute("*/7").second("00");
TimerConfig config = new TimerConfig();
config.setPersistent(false);
timer = timerService.createCalendarTimer(schedule, config);
}
@Timeout
@AccessTimeout(value = 20, unit = TimeUnit.MINUTES)
public void handleTimeout() {
workInNewThread();
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@TransactionTimeout(unit = TimeUnit.SECONDS, value = 900)
public void workInNewThread() {
// This can take anything from 1 sec to 15 min.
List<Object> objects = myManager.getAllTheDatabaseObjects();
}
}
但是,计时器似乎忽略了TransactionTimeout,因为它在5分钟后仍然超时(默认值)。如何覆盖默认超时以确保计时器完成作业?
答案 0 :(得分:1)
不确定我是否正确。 从你的代码看起来你从@Timeout方法调用workInNewThread(),但是有一个带有Tx属性的方法cleanup()。
我猜你从@Timeout调用同一个bean中的方法。 但在这种情况下,注释(@TxAttribute和TxTimeout)都不会生效,因为容器不控制内部方法调用。 您需要使用不同的EJB或自引用来让控制器执行此操作。 其他选项是直接注释超时方法。