Joseph Gagnon
Joseph Gagnon

Reputation: 2135

Spring boot: How to parameterize @Scheduled

I am new to Spring and have only scratched the surface of what can be done with it.

I have a situation where I need to set up a recurring task using the @Scheduled annotation. The rate is specified as a member field in an object that is passed to the class encapsulating the method representing the task.

I've used the mechanism that allows for accessing the configuration or environment, e.g. @Scheduled(fixedRateString = "${some.property:default}"); this works great.

What I don't know how to do is insert the value from an object into the @Scheduled.

For example:

class MyClass {
  private MyObject myObj;

  public MyClass(MyObject myObj) {
    this.myObj = myObj;
  }

  @Scheduled(fixedRateString = "${myObj.rate:5000}")
  private void someTask() {
    ...
  }
}

The code above, of course, does not work, I'm just giving an example of what I'm trying to do.

Any suggestions would be appreciated.

Upvotes: 6

Views: 26726

Answers (4)

Rawb
Rawb

Reputation: 347

Unfortunately the spring bean creation process will not read local variables like that.

You can use Spring's TaskScheduler class.

Essentially you just have to define a thread pool that you will use to run the scheduled tasks (as a bean) and run taskScheduler.schedule(runnable, new CronTrigger("* * * * *")). There is a detailed example here:

https://www.baeldung.com/spring-task-scheduler

Upvotes: 5

Dupeyrat Kevin
Dupeyrat Kevin

Reputation: 106

As you can see her : https://www.baeldung.com/spring-scheduled-tasks

You can do that like follow :

A fixedDelay task:

@Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds}")

A fixedRate task:

@Scheduled(fixedRateString = "${fixedRate.in.milliseconds}")

A cron expression based task:

@Scheduled(cron = "${cron.expression}")

Upvotes: 2

Andy Brown
Andy Brown

Reputation: 13019

Yes you can use the @Scheduled annotation to do that with a SpEL expression (available on the @Scheduled annotation since Spring 4.3.x). Here's an example:

@Slf4j
@Configuration
@EnableScheduling
public class ExampleClass {

  static class ScheduleCalculator {
    public String calc() {
      return "5000";
    }
  }

  @Bean("scheduleCalculator")
  public ScheduleCalculator createScheduleCalculator() {
    return new ScheduleCalculator();
  }

  @Scheduled(fixedRateString = "#{scheduleCalculator.calc()}")
  public void someTask() {
    log.info("Hello world");
  }
}

However, just because you can do it like this doesn't mean you necessarily should.

Your code may be easier to follow to folks that have to maintain it in the future if you use the spring task scheduler plus you get control of the thread pool used for scheduling instead of relying on the shared executor that all @Scheduled tasks get lumped into.

Upvotes: 7

DEBENDRA DHINDA
DEBENDRA DHINDA

Reputation: 1193

You can do like follow:

@Component
@ConfigurationProperties(prefix = "my.obj")
public class MyObject {

    private String cronExecExpr = "*/5 * * * * *";

    // getter and setter
}
class MyClass {
  private MyObject myObj;

  public MyClass(MyObject myObj) {
    this.myObj = myObj;
  }

  @Scheduled(cron = "${my.obj.cron-exec-expr:*/5 * * * * *}")
  private void someTask() {
    ...
  }
}

Upvotes: 2

Related Questions