アプリケーションでは、従来のSpring Webアプリケーション(システムTomcatにデプロイされている)からSpring Boot(V1.2.1)アプリケーションに変換したため、Quartzベースのスケジュールされたジョブが機能しなくなるという問題に直面します。
私はこれらのQuartzジョブを次のようにスケジュールします。
_// My own Schedule object which holds data about what to schedule when
Schedule schedule = scheduleService.get(id of the schedule);
String scheduleId = schedule.getId();
JobKey jobKey = new JobKey(scheduleId);
TriggerKey triggerKey = new TriggerKey(scheduleId);
JobDataMap jobData = new JobDataMap();
jobData.put("scheduleId", scheduleId);
JobBuilder jobBuilder = JobBuilder.newJob(ScheduledActionRunner.class)
.withIdentity(jobKey)
.withDescription(schedule.getName())
.usingJobData(jobData);
JobDetail job = jobBuilder.build();
TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger()
.forJob(jobKey)
.withIdentity(triggerKey)
.withDescription(schedule.getName());
triggerBuilder = triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(schedule.toCronExpression()));
Trigger trigger = triggerBuilder.build();
org.quartz.Scheduler scheduler = schedulerFactoryBean.getScheduler();
scheduler.scheduleJob(job, trigger);
_
ScheduledActionRunner
:
_@Component
public class ScheduledActionRunner extends QuartzJobBean {
@Autowired
private ScheduleService scheduleService;
public ScheduledActionRunner() {
}
@Override
public void executeInternal(final JobExecutionContext context) throws JobExecutionException {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
final JobDataMap jobDataMap = context.getMergedJobDataMap();
final String scheduleId = jobDataMap.getString("scheduleId");
final Schedule schedule = scheduleService.get(scheduleId);
// here it goes BANG since scheduleService is null
}
}
_
ScheduleService
は、Hibernateからデータをフェッチする従来のSpringサービスです。上で述べたように、これはSpringBootに移行するまでは問題なく機能しました。
このコードを従来のSpringアプリケーションで実装したとき、SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
はサービスの自動配線を処理するためのトリックを実行しました。
Spring Boot環境でこれを再び機能させるには何が必要ですか?
編集:
最後に、SpringのThreadPoolTaskSchedulerを優先して、Quartzの使用をやめることにしました。コードは大幅に簡素化され、期待どおりに機能します。
SpringBeanAutowiringSupportは、Webアプリケーションコンテキストを使用しますが、これはあなたのケースでは利用できません。クォーツにスプリングマネージドビーンズが必要な場合は、スプリングが提供するクォーツサポートを使用する必要があります。これにより、すべての管理対象Beanへのフルアクセスが可能になります。詳細については、Spring docsのquartzセクション( http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html )を参照してください。次のSpringマネージドBeanでのクォーツの使用例も参照してください。例はあなたのコードに基づいています。したがって、最初のコードスニペット(クォーツの初期化が行われる場所)を次のSpringの代替手段で変更できます。
ジョブ詳細ファクトリを作成する
@Component
public class ScheduledActionRunnerJobDetailFactory extends JobDetailFactoryBean {
@Autowired
private ScheduleService scheduleService;
@Override
public void afterPropertiesSet() {
setJobClass(ScheduledActionRunner.class);
Map<String, Object> data = new HashMap<String, Object>();
data.put("scheduleService", scheduleService);
setJobDataAsMap(data);
super.afterPropertiesSet();
}
}
トリガーファクトリを作成する
@Component
public class ActionCronTriggerFactoryBean extends CronTriggerFactoryBean {
@Autowired
private ScheduledActionRunnerJobDetailFactory jobDetailFactory;
@Value("${cron.pattern}")
private String pattern;
@Override
public void afterPropertiesSet() throws ParseException {
setCronExpression(pattern);
setJobDetail(jobDetailFactory.getObject());
super.afterPropertiesSet();
}
}
そして最後にSchedulerFactoryを作成します
@Component
public class ActionSchedulerFactoryBean extends SchedulerFactoryBean {
@Autowired
private ScheduledActionRunnerJobDetailFactory jobDetailFactory;
@Autowired
private ActionCronTriggerFactoryBean triggerFactory;
@Override
public void afterPropertiesSet() throws Exception {
setJobDetails(jobDetailFactory.getObject());
setTriggers(triggerFactory.getObject());
super.afterPropertiesSet();
}
}
私の答えはあなたの質問と完全には一致しませんが、Springは別の機能を公開します-任意のサービスでcron式ベースのスケジューラーを開始します。
Spring.Bootを使用すると、配置するだけでスケジューラーを使用するようにアプリケーションを構成できます。
@EnableScheduling
public class Application{
....
その後、@Service
のpublic
(!)メソッドに次のアノテーションを配置するだけです。
@Service
public class MyService{
...
@Scheduled(cron = "0 * * * * MON-FRI")
public void myScheduledMethod(){
....
}