Search code examples
javatimerjbossejb-3.0

EJB timer ignores TransactionTimeout


I have an EJB timer in an ear, deployed on JBoss 6.4. In 99% of all cases the timer works fine, but sometimes it takes a bit too long to finish and throws a PersistenceException: Transaction was rolled back in a different thread!.

I have found that this is due to a transacion timeout value that is too low. I do not want to edit the default value but rather override the method-specific timeout. To solve this I split the functionality into two methods: one method annotated with @Timeout and one which actually does the work.

Here is my timer implememntation:

@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();
    }
}

However, the timer seems to ignore the TransactionTimeout as it still times out after 5 minutes (default value). How can I override the default timeout to make sure that the timer finishes the job?


Solution

  • Not sure whether I get it correct. From your code it look like you call workInNewThread() from your @Timeout method, but there is a method cleanup() with a Tx attribute.

    I guess that you call methods in the same bean from your @Timeout. But in this case the annotations, neither @TxAttribute nor TxTimeout, will take effect as the container does not control the internal method invocation. You need to use a different EJB or a self reference to let the controller do that work. Other option is to annotate the timeout method directly.