Tal.Bary
Tal.Bary

Reputation: 450

Spring task:scheduler XML configuration problem

I have some functions in a Bean that I want to run every 5 seconds which the variable should be "generalized" not hard coded:

the working code looks as follows: (I have written in the relevant XML)

@Component
@EnableScheduling
public class CacheManager{


    @Scheduled(initialDelay=0,fixedDelay=5000)  
    public void updateConfigurations() {

        Some Code Here
    }

    @Scheduled(initialDelay=0,fixedDelay=5000)
    public void updateMapping() {

        Some Code Here

    }

}

Both functions execute every 5 seconds.

Now when I want to move it into XML:

<task:scheduler id="ttScheduler" pool-size="1" />

    <task:scheduled-tasks scheduler="ttScheduler">
        <task:scheduled ref="cacheManager" method="updateConfigurations" fixed-delay="5000" initial-delay="0" />
        <task:scheduled ref="cacheManager" method="updateMapping" fixed-delay="5000" initial-delay="0" />
    </task:scheduled-tasks>


@Component
public class CacheManager{


    public void updateConfigurations() {

        log.info("update configurations");

        Some Code

        log.info("end update configurations");
    }

    public void updateMapping() {

        Some Code Here

    }

}

both functions executes with no delay. output:

20190127-17:24:48.254  INFO [ttScheduler-1] CacheManager[109] - end update  configurations
20190127-17:24:48.255  INFO [ttScheduler-1] CacheManager[105] - update  configurations
20190127-17:24:48.282  INFO [ttScheduler-1] CacheManager[109] - end update  configurations
20190127-17:24:48.283  INFO [ttScheduler-1] CacheManager[105] - update  configurations
20190127-17:24:48.311  INFO [ttScheduler-1] CacheManager[109] - end update  configurations
20190127-17:24:48.312  INFO [ttScheduler-1] CacheManager[105] - update  configurations
20190127-17:24:48.337  INFO [ttScheduler-1] CacheManager[109] - end update  configurations
20190127-17:24:48.337  INFO [ttScheduler-1] CacheManager[105] - update  configurations
20190127-17:24:48.362  INFO [ttScheduler-1] CacheManager[109] - end update  configuration
...
...

Update: I have fixed the typo: to fixed-delay (generates the same output) the application is a web app that runs under tomcat 8.

I made small app (not web this time) as suggested by Dmitry Khamitov. It does work as a single executable app, BUT still as I wrote the same code just not works under web app environment.

The sample of the working test code:

public class SpringTestApplication {

    private final AtomicInteger counter = new AtomicInteger();

    public void updateConfigurations() throws InterruptedException {

        if (counter.getAndIncrement() == 0) {

            Date instant = new Date(System.currentTimeMillis());
            SimpleDateFormat sdf = new SimpleDateFormat( "HH:mm:ss" );
            String time = sdf.format( instant );
            System.out.println( "Time: " + time );

            Thread.sleep(5000);
        }

        Date instant = new Date(System.currentTimeMillis());
        SimpleDateFormat sdf = new SimpleDateFormat( "HH:mm:ss" );
        String time = sdf.format( instant );
        System.out.println( "Time: " + time );
    }

    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("spring.xml");
    }
}

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="http://www.springframework.org/schema/task 
        http://www.springframework.org/schema/task/spring-task-4.2.xsd
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <bean id="SpringTestApplication" class="com.example.demo.SpringTestApplication" scope="singleton">

    </bean>

    <task:scheduler id="ttScheduler" pool-size="1"/>
    <task:scheduled-tasks scheduler="ttScheduler">
        <task:scheduled ref="SpringTestApplication" method="updateConfigurations" fixed-delay="5000" initial-delay="0"/>
    </task:scheduled-tasks>



</beans>

Upvotes: 0

Views: 2729

Answers (1)

Dmitry Khamitov
Dmitry Khamitov

Reputation: 3276

Probably this is because in XML you use fixed-rate, whereas in Java config you use fixed-delay. As the Official Spring Doc states:

...fixed delay indicating the number of milliseconds to wait after each task execution has completed. Another option is fixed-rate, indicating how often the method should be executed regardless of how long any previous execution takes...

So if Some Code in your example took much more time than your fixed-rate in some interval, then the consecutive tasks might have just queued up during that interval. Once that heavy execution is finished and if the next executions happen to be lightweight then you will see what you see in your logs until the ScheduledExecutorService's queue is drained. After that your lightweight tasks will start to run every fixed-rate ms.

Try searching the logs for the first executions to see the time taken by them. You can also comment out Some Code and restart your application in attempt of locating the root cause. Below is my simulated example which is expected to run every 1 sec but its first run takes 5 sec:

public class CacheManager {
    private static final Logger LOG = LoggerFactory.getLogger(CacheManager.class);

    private final AtomicInteger counter = new AtomicInteger();

    public void updateConfigurations() throws InterruptedException {
        LOG.info("update configurations");
        if (counter.getAndIncrement() == 0) {
            Thread.sleep(5000);
        }
        LOG.info("end update configurations");
    }

    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("spring.xml");
    }
}
<beans ...>
    <bean id="cacheManager" class="CacheManager"/>

    <task:scheduler id="ttScheduler" pool-size="1"/>
    <task:scheduled-tasks scheduler="ttScheduler">
        <task:scheduled ref="cacheManager" method="updateConfigurations" fixed-rate="1000" initial-delay="0"/>
    </task:scheduled-tasks>
</beans>

Output:

21:00:58.703 [ttScheduler-1] INFO  CacheManager - update configurations
21:01:03.706 [ttScheduler-1] INFO  CacheManager - end update configurations
21:01:03.706 [ttScheduler-1] INFO  CacheManager - update configurations
21:01:03.707 [ttScheduler-1] INFO  CacheManager - end update configurations
21:01:03.707 [ttScheduler-1] INFO  CacheManager - update configurations
21:01:03.707 [ttScheduler-1] INFO  CacheManager - end update configurations
21:01:03.707 [ttScheduler-1] INFO  CacheManager - update configurations
21:01:03.707 [ttScheduler-1] INFO  CacheManager - end update configurations
21:01:03.707 [ttScheduler-1] INFO  CacheManager - update configurations
21:01:03.708 [ttScheduler-1] INFO  CacheManager - end update configurations
21:01:03.708 [ttScheduler-1] INFO  CacheManager - update configurations
21:01:03.708 [ttScheduler-1] INFO  CacheManager - end update configurations
21:01:04.707 [ttScheduler-1] INFO  CacheManager - update configurations
21:01:04.708 [ttScheduler-1] INFO  CacheManager - end update configurations
21:01:05.706 [ttScheduler-1] INFO  CacheManager - update configurations
21:01:05.706 [ttScheduler-1] INFO  CacheManager - end update configurations
21:01:06.704 [ttScheduler-1] INFO  CacheManager - update configurations
21:01:06.704 [ttScheduler-1] INFO  CacheManager - end update configurations

Upvotes: 1

Related Questions