In my Spring application, I have an abstract class with a function functionA
and an abstract function functionB
. functionA
calls functionB
and the latter is implemented in the child classes.
I want functionA
to be a scheduled function (running based on a cron string) in all the child classes, but the schedule in each child class is different.
I considered using @Scheduled
annotation in the abstract class' functionA
, with the child classes having @Component
annotations. But I am unable to figure out how to control the cron strings for each child class.
How do i achieve this? Is there a way to make the cron
value in the @Scheduled
annotation accept a class variable?
In my Spring application, I have an abstract class with a function functionA
and an abstract function functionB
. functionA
calls functionB
and the latter is implemented in the child classes.
I want functionA
to be a scheduled function (running based on a cron string) in all the child classes, but the schedule in each child class is different.
I considered using @Scheduled
annotation in the abstract class' functionA
, with the child classes having @Component
annotations. But I am unable to figure out how to control the cron strings for each child class.
How do i achieve this? Is there a way to make the cron
value in the @Scheduled
annotation accept a class variable?
1 Answer
Reset to default 0I do not know how you can achieve what you want using @Scheduled
in an abstract class and defining the cron expression in its implementations.
I guess it is either impossible or, at the very least, not simple.
But I would suggest the following approach:
- add one more abstract method
getCronTrigger
- implement
getCronTrigger
in the abstract class's implementation so they return neededCronTrigger
- schedule tasks in some post construct
- using autowired list of all beans that implement the abstract class
- using autowired
taskScheduler
The approach is inspired by baeldung and another SO answer
But there are changes for your specific question.
Example is written in Kotlin, but it could be easily rewritten to Java.
@Configuration
// EnableScheduling is needed to have bean ThreadPoolTaskScheduler in the Spring context
// other approach - define your own bean ThreadPoolTaskScheduler
@EnableScheduling
class ScheduledConfigs
@Component
class Schedule(
private val tasks: List<ScheduledTask>,
private val taskScheduler: ThreadPoolTaskScheduler
) {
@PostConstruct
fun schedule() {
for (task in tasks) {
println("Schedule task (${task.javaClass.simpleName}) with cron ${task.getCronTrigger()}")
taskScheduler.schedule(task, task.getCronTrigger());
}
}
}
abstract class ScheduledTask: Runnable {
override fun run() {
println("${javaClass.simpleName} starts")
doWork()
println("${javaClass.simpleName} did its work")
}
abstract fun doWork()
abstract fun getCronTrigger(): CronTrigger
}
@Component
class RealTask1: ScheduledTask() {
override fun getCronTrigger(): CronTrigger = CronTrigger("*/30 * * * * ?")
override fun doWork() {
println("${javaClass.simpleName} does its job every 30 seconds")
}
}
@Component
class RealTask2: ScheduledTask() {
override fun getCronTrigger(): CronTrigger = CronTrigger("0 * * * * ?")
override fun doWork() {
println("${javaClass.simpleName} does its job every minute")
}
}