0

I've added a method with @Scheduled(fixedDelay = 0) annotation, and within the method I'm using some repository, initialized in the class with: @Autowired private ContactRepository contactRepository;

About the repository: public interface ContactRepository extends CrudRepository<Contact, String>

The problem is that I'm getting an exception:

java.lang.IllegalArgumentException: null
    at java.util.concurrent.ScheduledThreadPoolExecutor.scheduleWithFixedDelay(ScheduledThreadPoolExecutor.java:589) ~[na:1.8.0_151]
    at java.util.concurrent.Executors$DelegatedScheduledExecutorService.scheduleWithFixedDelay(Executors.java:738) ~[na:1.8.0_151]
    at org.springframework.scheduling.concurrent.ConcurrentTaskScheduler.scheduleWithFixedDelay(ConcurrentTaskScheduler.java:235) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleFixedDelayTask(ScheduledTaskRegistrar.java:511) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleFixedDelayTask(ScheduledTaskRegistrar.java:485) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleTasks(ScheduledTaskRegistrar.java:362) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.scheduling.config.ScheduledTaskRegistrar.afterPropertiesSet(ScheduledTaskRegistrar.java:332) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:280) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:211) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:102) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:400) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:354) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:888) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:161) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at com.user.app.Main.main(Main.java:17) [classes/:na]

Update:

When I'm using fixedDelay = 1 (or more than that), it works. Why?

Roni Koren Kurtberg
  • 495
  • 1
  • 8
  • 18

3 Answers3

1

According to the Javadoc for ScheduledExecutorService.scheduleWithFixedDelay(Runnable, long, long, TimeUnit), IllegalArgumentException occurs when period <= 0. So presumably @Scheduled(fixedDelay = 0) causes period to be 0 resulting in this exception to occur.

Perhaps a Scheduled method is not what you actually want? If you're looking to execute a method after start up maybe this question will help: Execute method on startup in spring

d.j.brown
  • 1,822
  • 1
  • 12
  • 14
  • I want a dymanic time scheduled task. My intention is to run the method after the application is ready -> doing some logic and create a new delay until the next task. Right now I do it by defining the fixedDelay to be 1 and within the method, I'm going to sleep as I want -> by this way I'm creating a run-time dependent scheduler... – Roni Koren Kurtberg May 06 '18 at 10:27
0

the fixedDelay is a period how often the scheduled task gets executed in milliseconds. You can’t set it to 0 since it doesn’t make sense and you got corresponding IllegalArgumentexception

Roman T
  • 1,400
  • 5
  • 18
  • 31
0

@Scheduler annotation delegates the call to the ScheduledThreadPoolExecutor where fixedDelay parameter is long delay.

This is the implementation of the method of Oracle JDK:

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                 long initialDelay,
                                                 long delay,
                                                 TimeUnit unit) {
    if (command == null || unit == null)
        throw new NullPointerException();
    if (delay <= 0L)
        throw new IllegalArgumentException();
    ScheduledFutureTask<Void> sft =
        new ScheduledFutureTask<Void>(command,
                                      null,
                                      triggerTime(initialDelay, unit),
                                      -unit.toNanos(delay),
                                      sequencer.getAndIncrement());
    RunnableScheduledFuture<Void> t = decorateTask(command, sft);
    sft.outerTask = t;
    delayedExecute(t);
    return t;
}

Where we clearly can see that if (delay <= 0L) throw new IllegalArgumentException();

And what is the point of setting 0? It's really an illegal argument. Can you perform some action every zero second? No. It basically will mean that those actions occurs simultaneously. You need at lease some minimal period between them.

Then public abstract long initialDelay will allow you to specify first delay before executing the method.

Number of milliseconds to delay before the first execution of a fixedRate() or fixedDelay() task.

Example:

@Scheduled(initialDelay = 1000, fixedDelay = 10000)

The task will be executed a first time after the initialDelay (1s) – and it will continue to be executed according to the fixedDelay (every 10s).

J-Alex
  • 6,881
  • 10
  • 46
  • 64
  • sorry, but I have spoke about dynamic delay after each task. With random sleeping I'm getting that, do you have another solution instead of that? – Roni Koren Kurtberg May 06 '18 at 12:07
  • @Roni Kurtberg I have, but this is out of scope of original question. You're posting entirely different question in the comment. https://stackoverflow.com/questions/14630539/scheduling-a-job-with-spring-programmatically-with-fixedrate-set-dynamically/14632758#14632758 – J-Alex May 06 '18 at 12:59