9

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

tiagocarvalho92
  • 375
  • 1
  • 7
  • 17
  • Not. That is not what cronjobs are used for / how they are supposed to work. – luk2302 Nov 10 '17 at 10:29
  • See e.g. how to changed `fixedDelay`: https://stackoverflow.com/q/14630539/2442804 - `cron` is even more complex. – luk2302 Nov 10 '17 at 10:30
  • What should be a best practice to achieve this then? – tiagocarvalho92 Nov 10 '17 at 10:33
  • Reimplement the entire cron job setup, debug into spring code and analyze where the annotation gets evaluated and try to reproduce that. – luk2302 Nov 10 '17 at 10:34
  • 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 Nov 10 '17 at 10:41
  • If configuration is dynamic, how do you imagine an application should know, when to look for schedule in database? Each query to DB costs much – WeGa Nov 10 '17 at 10:45
  • We could store the expression in a variable, and then in the GUI the user updates that variable, not that expensive i guess – tiagocarvalho92 Nov 10 '17 at 10:47

5 Answers5

11

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.

Mickael
  • 4,458
  • 2
  • 28
  • 40
  • ... and keep track of the previous task and cancel its schedule as soon as you have a new schedule for it. – luk2302 Nov 10 '17 at 10:49
  • i'm trying to implement this and i came up with one question. Now that i won't have the annotation where in time and code should i load from the database all the cron expressions and schedule all the jobs? – tiagocarvalho92 Nov 10 '17 at 13:24
  • It's hard to say because I don't really know what your application is supposed to do. IMO, a good solution is to have a dedicated `Component` for this. Your `Component` will init all the jobs using `init-method` or `post-construct`. – Mickael Nov 10 '17 at 13:53
  • 1
    I found one way to do it ;) thanks for all the suggestions. – tiagocarvalho92 Nov 10 '17 at 14:33
  • @tiagocarvalho92 can you mention how you handled that, is it by using `Component`? – Yachitha Sandaruwan Feb 28 '23 at 07:10
4

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

Dexters
  • 2,419
  • 6
  • 37
  • 57
Makoton
  • 443
  • 3
  • 14
1

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();
}
Vipin CP
  • 3,642
  • 3
  • 33
  • 55
0

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

WeGa
  • 801
  • 4
  • 10
  • 24
  • That's one option but i want to be able to change that in runtime. Your solution is the same as hardcoded values because it's not possible to change without a deploy – tiagocarvalho92 Nov 10 '17 at 10:33
  • Oh, I see. Please update your question with that information – WeGa Nov 10 '17 at 10:33
  • 1
    @WeGa that is already in the question: *"Now i want to be able to through the database update this cron expression and reschedule the specific job"*. – luk2302 Nov 10 '17 at 10:35
  • @luk2302, actually, it's only told about where OP wants to hold his configuration, and not how dynamically it should be. I just want to have more concise question)) – WeGa Nov 10 '17 at 10:42
0

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

Ayo K
  • 1,719
  • 2
  • 22
  • 34