Reputation: 77
I am trying to schedule my rest service(with GET method) using
@Scheduled(cron = xyzzy.getTimeSchedule())
The schedule details are expected to be obtained from application properties from cloud during the application start up. however I get "The value for Annotation attribute Scheduled.cron must be a constant expression" compile time error. Please suggest. Also what might be the underlying issue like with the Spring annotation and the properties being available during the time application start up. Please guide or direct me to understand.TIA.
Upvotes: 3
Views: 2360
Reputation: 77
@ManagedConfiguration
private ConfigClass configClass;
@bean
public String getSchedulerValue() {
return configClass.getSchedule();}
@Scheduled(cron="#{getSchedulerValue}")
Upvotes: 0
Reputation: 77
Finally this is what worked for me. I have my property stored as key : value pair over the cloud.like so..
xyz.Schedule = */5 * * * * ;
public Class testController {
@Autowired
private Type type;
@Scheduled(cron = "${type.getSchedule()}")
@GetMapping(path = "/", produces = "application/json")
public void getmethod() { blah blah } }
I ran my application successfully and was being able to populate the property configured over cloud at the start of application, and was able to get response for my api as well.
Things I tried: As suggested by Shekhar Rai in this discussion chain, declaring it as final variable, but was unable to access it in my method.
tried wrapping the method as a runnable task, couldn't do so.
arrived at: @Scheduled.cron always expects a constant parameter(like a string), but get() is dynamic , therefore wrapped it as a constant parameter.
Upvotes: 1
Reputation: 2058
Using @Scheduled annotation you cannot provide a method for cron-expression which comes from the cloud. As java annotation needs constant-expression, which is a variable whose value cannot change once it has been assigned. For that, you need to use final
keyword.
public static final String TIME_SCHEDULE = "0 0/30 8-10 * * *";
Then use that constant expression in your scheduler method,
@Scheduled(cron = TIME_SCHEDULE)
In your case, you should go for @TaskScheduler (from doc)
Task scheduler interface that abstracts the scheduling of Runnables based on different kinds of triggers. This interface is separate from SchedulingTaskExecutor since it usually represents for a different kind of backend, i.e. a thread pool with different characteristics and capabilities. Implementations may implement both interfaces if they can handle both kinds of execution characteristics.
Replacing @Scheduled annotation with @TaskScheduler
First, autowire TaskScheduler and make sure that you annotated your main class with @EnableScheduling annotation to provide bean for TaskScheduler.
@Autowired
private TaskScheduler scheduler;
Now you need to schedule providing Runnable and CronTrigger arguments. It schedules the given Runnable, invoking it whenever the trigger indicates a next execution time.
That means you need to wrap your logic(currently this is the code from your @Schduled method body) into Runnable instance. And your xyzzy.getTimeSchedule()
should be provided to CronTrigger constructor.
Runnable runnableTask = () -> {
//call REST API here
};
scheduler.schedule(runnableTask, new CronTrigger(xyzzy.getTimeSchedule());
Now you get rid of "The value for Annotation attribute Scheduled.cron must be a constant expression"
Upvotes: 2