Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Timer Service running multiple times

I have created a function doWork() that's scheduled to run every day at 1:00 am, the function is as follows:

@Schedule(hour = "1", persistent = false)
    public void doWork()
    {
        System.out.println("Starting .....\nTIME: " + System.currentTimeMillis());
        System.out.println("this : " + this);

        //Some code here, if-conditions and try/catch blocks. No loops

        System.out.println("Exiting .....\nTIME: " + System.currentTimeMillis());
        System.out.println("this : " + this);
    }

The problem is that this function runs more than once, not as scheduled.

Once I created it, it ran exactly as expected (everyday at 1:00:00 am exactly). A few days later, it started running at 1:03:00 (which doesn't make any sense since it's nonpersistent and there was no downtime in the server anyway). After that the function started running more than once with very short intervals in between (seconds difference)

Does anyone know what might cause this, or tell me what I can do to fix it?

[EDIT]: Environment details

Application Server: WebSphere Application Server 8.5.5

IDE: Rational Application Developer 9.1

Database Management System: IBM DB2 10.1

like image 371
Ahmed Anwar Avatar asked Aug 04 '16 12:08

Ahmed Anwar


1 Answers

I believe that you are observing the container attempting to retry a failed doWork() call.

The EJB timer service is transactional.

If the execution of a timeout method throws any runtime exception then the transaction will be rolled back and the container will attempt to execute the timeout method again. See §18.2.8 Transactions of the EJB 3.1 Specification.

Additionally, if the transaction timeout expires, some implementations will just mark the current transaction for rollback and continue with processing. This will result in the timer call failing eventually and a retry will be attempted.

This retry mechanism is not well specified and the actual behaviour varies from implementation to implementation. Some will retry forever and others will give up after some number of attempts. WebSphere for example provides a way to specify the retry strategy. See Creating timers using the EJB timer service for enterprise beans.

Finally if your application is running across multiple nodes then you probably have a timer running per server instance. According to §18.2.3 Non-persistent Timers of the spec:

For automatic non-persistent timers, the container creates a new non-persistent timer during application initialization for each JVM across which the container is distributed.

If these are all performing the same task then that is likely to cause enough chaos to generate errors, rollbacks and subsequent retries.

like image 51
Steve C Avatar answered Nov 18 '22 13:11

Steve C