8
votes

I have around 10 jobs scheduled with @Scheduled and a hardcoded cron expression like this:

@Scheduled(cron = "* * 1 * * *")
public void testMethod(){
    doSomething();
}

Now i want to be able to through the database update this cron expression and reschedule the specific job in runtime.

Does anyone knows how to do this?

Thanks

5
Not. That is not what cronjobs are used for / how they are supposed to work. - luk2302
See e.g. how to changed fixedDelay: stackoverflow.com/q/14630539/2442804 - cron is even more complex. - luk2302
What should be a best practice to achieve this then? - tiagocarvalho92
Reimplement the entire cron job setup, debug into spring code and analyze where the annotation gets evaluated and try to reproduce that. - luk2302
That is too much effort for this task. I thought that something was already done to handle this. Maybe create an answer with that so i can accept it - tiagocarvalho92

5 Answers

11
votes

If you want to configure the scheduling of job at runtime, I don't think you can use the annotation @Scheduled.

You can use your own scheduler instead from Spring documentation :

scheduler.schedule(task, new CronTrigger("0 15 9-17 * * MON-FRI"));

Then, if you want to change the configuration, you can cancel the scheduling and create a new one.

TaskScheduler return a ScheduledFuture that you should save somewhere and it can be cancelled with cancel(...) method.

4
votes

I think that @Scheduled no support this feature (must be interesting implement that). For advance scheduling feature you need to use quartz or other scheduler solution. My answer is based on Quartz Solution:

@Component
class ReschedulerComponent{

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    public void reSchedule(){

    Trigger oldTriger = schedulerFactoryBean.getScheduler().getTrigger("my_custom_trigger");

        Trigger myNewTrigger = TriggerBuilder
                .newTrigger()
                .forJob(jobDetail) // Name of your job
                .withIdentity("my_custom_trigger")
                .startAt(myNewDATE)
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionFireNow())
                .build();

    schedulerFactoryBean.getScheduler().rescheduleJob(oldTriger.getKey(), myNewTrigger);
    }

}

Quick introduction: https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/scheduling.html

0
votes

I think you should look at this resource You can programmatically create scheduled jobs. So if you annotate your method with @PostConstruct it should pick it when the application starts and run at the scheduled time

https://www.programcreek.com/java-api-examples/index.php?api=org.quartz.impl.triggers.SimpleTriggerImpl

http://www.quartz-scheduler.org/api/2.2.1/org/quartz/impl/triggers/SimpleTriggerImpl.html

0
votes

If you want to configure schedule of the job, so that you don't need to change the code, I suggest you to extract value in property stored in some configuration.properties, then access to it in code with @Value.

UPD: found this topic, maybe you find it useful Spring Scheduler change cron expression dynamically

0
votes

This can be done by specifying the cron expression in your property place holder as mentioned below. Add below code in @configuration class.

@Bean
    public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {

        PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer();
        properties.setLocation(new ClassPathResource("test.properties"));
    return properties;
    }

Now test.properties will be available in your placeholder. Test.properties shown below

variable.name.inside.properties= 00 39 05 * * *

Then inside your scheduler class add

    @Scheduled(cron = "${variable.name.inside.properties}")
public void testMethod(){
    doSomething();
}