Dynamic job scheduling in spring boot with quartz scheduler

shashank :

I want to schedule jobs dynamically based on the schedule configuration provided by the user from the UI. When ever user save the new schedule configuration from the UI then the process has to invoke new job with the new scheduled parameters. There can be n number of configurations as such to execute the same job. Spring supports the implementation of job detail and trigger as following.

Defining jobdetail:

@Bean
public JobDetail jobDetail() {
    return JobBuilder.newJob().ofType(SampleJob.class)
      .storeDurably()
      .withIdentity("Qrtz_Job_Detail")  
      .withDescription("Invoke Sample Job service...")
      .build();
}

Defining trigger:

@Bean
public Trigger trigger(JobDetail job) {
    return TriggerBuilder.newTrigger().forJob(job)
      .withIdentity("Qrtz_Trigger")
      .withDescription("Sample trigger")
      .withSchedule(simpleSchedule().repeatForever().withIntervalInHours(1))
      .build();
}

How can I pass the parameters for job detail and trigger dynamically based on the parameters provided by the user?

Nikolay Hristov :

The easiest way is to make some configuration by extending SpringBeanJobFactory and @Override createJobInstance method. Then you need to define SchedulerFactoryBean and finally your Scheduler:

@Configuration
public class SchedulerConfiguration {

    public class AutowireCapableBeanJobFactory extends SpringBeanJobFactory {

        private final AutowireCapableBeanFactory beanFactory;

        @Autowired
        public AutowireCapableBeanJobFactory(AutowireCapableBeanFactory beanFactory) {
            Assert.notNull(beanFactory, "Bean factory must not be null");
            this.beanFactory = beanFactory;
        }

        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            Object jobInstance = super.createJobInstance(bundle);
            this.beanFactory.autowireBean(jobInstance);
            this.beanFactory.initializeBean(jobInstance, null);
            return jobInstance;
        }
    }

    @Bean
    public SchedulerFactoryBean schedulerFactory(ApplicationContext applicationContext) {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setJobFactory(new AutowireCapableBeanJobFactory(applicationContext.getAutowireCapableBeanFactory()));
        return schedulerFactoryBean;
    }

    @Bean
    public Scheduler scheduler(ApplicationContext applicationContext) throws SchedulerException {
        Scheduler scheduler = schedulerFactory(applicationContext).getScheduler();
        scheduler.start();
        return scheduler;
    }
}

Then anywhere in your application, for example in a RestController you can access the scheduler and schedule a new job:

@RestController
public class ScheduleController {

    @Autowired
    private Scheduler scheduler;

    @GetMapping(value = "/schedule/{detail}/{desc}")
    public String scheduleJob(@PathVariable(value = "detail") String detail, @PathVariable(value = "desc") String desc) throws SchedulerException {
        JobDetail job = newJob(detail, desc);
        return scheduler.scheduleJob(job, trigger(job)).toString();
    }

    private JobDetail newJob(String identity, String description) {
        return JobBuilder.newJob().ofType(SimpleJob.class).storeDurably()
                .withIdentity(JobKey.jobKey(identity))
                .withDescription(description)
                .build();
    }

    private SimpleTrigger trigger(JobDetail jobDetail) {
        return TriggerBuilder.newTrigger().forJob(jobDetail)
                .withIdentity(jobDetail.getKey().getName(), jobDetail.getKey().getGroup())
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1))
                .build();
    }
}

You can control all schedules (pause, stop, restart, delete, etc...) from your Scheduler - look at the documentation

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=150525&siteId=1