Reputation: 2135
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
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
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
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
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