在下一次调用之前中断spring调度程序任务 [英] Interrupt spring scheduler task before next invocation

查看:1165
本文介绍了在下一次调用之前中断spring调度程序任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Spring-Boot应用程序,它将成为我们要触发的其他几个进程的编排服务。我目前设置使用Spring Scheduling从数据库动态拉crons。我抛出了一个rest方法来触发该过程从数据库中提取新的cron信息。这个逻辑都工作正常。唯一的问题是它不使用新的cron信息,直到下一次计划运行,得到真正的问题。 有一种方法可以中断当前触发器,并使用更新的cron信息重新计划一次。以下是应用程序的参考:

I have a Spring-Boot application which is going to be an orchestration service for several other processes we want to trigger. I have it currently set up using Spring Scheduling pulling crons dynamically from a database. I threw in a rest method to trigger the process to pull new cron information from the database. This logic all works correctly. The only "issue" is that it doesn't use the new cron information until the next scheduled run which gets to the real question. Is there a way to interrupt the current Trigger and schedule one again using the updated cron information. Here is the application for reference:

package com.bts.poc;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@SpringBootApplication
@EnableScheduling
@RestController
@RequestMapping("/APSCommon/Scheduling")
public class Application implements SchedulingConfigurer {

    @Autowired
    private DynamicCron dynamicCron;
    @Autowired
    PropertyManager propertyManager;

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class);
    }

    private String cronConfig() {
        String cronTabExpression = propertyManager.getProperty("COMPANY", "JOB_NAME","CRON_EXPRESSION");
        return cronTabExpression;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(new Runnable() {
            @Override
            public void run() {
                dynamicCron.runJob();
            }
        }, new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                String cron = cronConfig();
                CronTrigger trigger = new CronTrigger(cron);
                Date nextExec = trigger.nextExecutionTime(triggerContext);
                DynamicCron.cronExpression = cron;
                return nextExec;
            }
        });
    }

    @RequestMapping(value = "/reloadScheduling", method = RequestMethod.GET)
    public String reloadScheduling() {
        PropertyManager.setResetProperties(true);
        return "schedules will be altered next run";
    }
}


推荐答案

使用SchedulingConfigurer-> configureTasks你不能访问我使用的Spring版本(4.2.7.RELEASE)中的ScheduledFuture。从几个帖子我已经阅读它被提到作为未来的可能功能。我做了以下事情:

So using SchedulingConfigurer->configureTasks you can't get access to the ScheduledFuture(s) in the Spring version I am using (4.2.7.RELEASE). From several posts I have read it has been mentioned as possible functionality for the future. I got around this by doing the following:

package com.bts.poc;

import com.bts.poc.service.DynamicCron;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.ScheduledFuture;

@SpringBootApplication(exclude = MessageSourceAutoConfiguration.class)
@EnableScheduling
@RestController
public class Application extends SpringBootServletInitializer {

    @Autowired
    private DynamicCron dynamicCron;
    @Autowired
    private PropertyManager propertyManager;
    private static List<ScheduledFuture> scheduledFutures = new ArrayList<>();
    private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
    private static TaskScheduler scheduler;

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    private String cronConfig() {
        return propertyManager.getProperty("COMPANY", "JOB_NAME", "CRON_EXPRESSION");
    }

    @RequestMapping(value = {"scheduling/start"}, method = RequestMethod.GET)
    public @ResponseBody String startScheduling() {
        scheduleAll();

        LOGGER.info("Scheduling of jobs has been started.");
        return "Scheduling of jobs has been started.";
    }

    @RequestMapping(value = {"scheduling/cancel"}, method = RequestMethod.GET)
    public @ResponseBody String cancelScheduling() {
        cancelAll();

        LOGGER.info("Cancelling all scheduled jobs.");
        return "Cancelling all scheduled jobs.";
    }

    private void scheduleAll() {
        LOGGER.info("Scheduling all applications to run.");
        cancelAll();

        //eventually go through the database and load all jobs to be scheduled here.
        schedule(cronConfig());
    }

    /**
     * Cancel all the scheduled reports
     */
    private void cancelAll() {
        for (ScheduledFuture scheduledFuture : scheduledFutures) {
            scheduledFuture.cancel(true);
        }
        scheduledFutures.clear();
    }

    /**
     * Schedule the scheduled report with the given cron schedule information
     */
    private void schedule(String cronSchedule) {
        TimeZone tz = TimeZone.getDefault();
        LOGGER.info("Setting up application {} to execute with cron string: '{}'.", cronSchedule);
        CronTrigger trigger = new CronTrigger(cronSchedule, tz);

        scheduler = scheduler();
        if (scheduler == null) {
            LOGGER.error("Unable to schedule job as scheduler was not found");
            return;
        }

        ScheduledFuture<?> future = scheduler.schedule(new DynamicCron(), trigger);
        scheduledFutures.add(future);
    }

    @Bean
    public TaskScheduler scheduler() {
        if (scheduler == null) {
            ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
            scheduler.setPoolSize(10);
            scheduler.afterPropertiesSet();
        }
        return scheduler;
    }
}


$ b $ p这基本上复制了ScheduledTaskRegistrar提供的功能, ScheduledFuture(s)。希望这可以帮助未来的别人。

This basically replicates the functionality the ScheduledTaskRegistrar provides allowing you manage the ScheduledFuture(s). Hopefully this can help someone else in the future.

这篇关于在下一次调用之前中断spring调度程序任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆