Java 石英调度器在通过Spring 4配置时不触发作业
我从某个时候开始尝试设置一个小程序,使用Spring和Quartz来安排任务。我没有幸运地遵循了其他一些类似的答案。 目前,我认为我已经正确地配置了,我没有看到更多的异常,但我的工作似乎还没有开始 在Spring生成的log.out中,我在末尾看到以下消息: 2015-06-04T15:46:57.928调试 [org.springframework.core.env.PropertySourcesPropertyResolver] 在中搜索键“spring.liveBeansView.mbeanDomain” [系统属性]2015-06-04T15:46:57.929调试 [org.springframework.core.env.PropertySourcesPropertyResolver] 在中搜索键“spring.liveBeansView.mbeanDomain” [系统环境]2015-06-04T15:46:57.929调试 [org.springframework.core.env.PropertySourcesPropertyResolver]可以 在任何属性中都找不到键“spring.liveBeansView.mbeanDomain” 来源返回[null] 我会给你看我的密码 这是我启动计划程序的类:Java 石英调度器在通过Spring 4配置时不触发作业,java,spring,quartz-scheduler,Java,Spring,Quartz Scheduler,我从某个时候开始尝试设置一个小程序,使用Spring和Quartz来安排任务。我没有幸运地遵循了其他一些类似的答案。 目前,我认为我已经正确地配置了,我没有看到更多的异常,但我的工作似乎还没有开始 在Spring生成的log.out中,我在末尾看到以下消息: 2015-06-04T15:46:57.928调试 [org.springframework.core.env.PropertySourcesPropertyResolver] 在中搜索键“spring.liveBeansView.mbea
public class JobRunner {
public static void main(String[] args) throws SchedulerException {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(WhatsTheTimeConfiguration.class);
AutowiringSpringBeanJobFactory autowiringSpringBeanJobFactory = new AutowiringSpringBeanJobFactory();
autowiringSpringBeanJobFactory.setApplicationContext(applicationContext);
SpringBeanJobFactory springBeanJobFactory = new SpringBeanJobFactory();
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setTriggers(trigger());
schedulerFactoryBean.setJobFactory(springBeanJobFactory);
schedulerFactoryBean.start();
}
private static SimpleTrigger trigger() {
return newTrigger()
.withIdentity("whatsTheTimeJobTrigger", "jobsGroup1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(1)
.repeatForever())
.build();
}
}
我想提到的是,如果我使用schedulerFactoryBean.getScheduler.start方法,它会在调度器上抛出一个空指针异常,这就是我在工厂上调用start的原因
AutowiringSpringBeanJobFactory类是从stackoverflow中的另一个答案复制粘贴的。我决定这么做,因为我找到的所有其他答案都是通过xml完成的配置,我不想使用xml
public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
ApplicationContextAware {
private transient AutowireCapableBeanFactory beanFactory;
@Override
public void setApplicationContext(final ApplicationContext context) {
beanFactory = context.getAutowireCapableBeanFactory();
}
@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
}
}
这是表示我要触发的作业的类:
@Component
public class WhatsTheTimeManager extends QuartzJobBean {
@Autowired
private WhatsTheTime usecase;
@Autowired
private LocationRetriever locationDataProvider;
public WhatsTheTimeManager() {
}
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
usecase.tellMeWhatsTheTimeIn(locationDataProvider.allLocations());
}
public void setUsecase(WhatsTheTime usecase) {
this.usecase = usecase;
}
public void setLocationDataProvider(LocationRetriever locationDataProvider) {
this.locationDataProvider = locationDataProvider;
}
}
我的Spring配置是进行组件扫描,非常简单:
@Configuration
@ComponentScan(basePackages = "com.springpractice")
public class WhatsTheTimeConfiguration {
}
从这一点上说,我拥有的只是一些接口、组件和域对象,但我也会粘贴它们,以防我忘记了什么:
public interface LocationRetriever {
List<String> allLocations();
}
最后一个细节,可能很有趣。
我在库中使用的版本如下:
石英2.2.1
弹簧4.1.6.1释放
当我运行应用程序时,我希望这些国家的时间每秒都被打印出来,但事实并非如此
如果您想克隆代码并亲自尝试查看,您可以在这个git站点找到它。如果您愿意,请随意使用fork:代码中的主要错误是您没有让Spring为您处理调度 虽然您可以像其他代码一样在代码中使用Quartz,但与Spring集成的想法是告诉Spring您希望完成的工作,并让Spring为您完成艰巨的工作 为了允许Spring运行Quartz调度,您需要将作业、JobDetail和触发器声明为bean Spring只处理在Spring生命周期中创建的bean,即使用注释或XML,而不处理使用新语句在代码中创建的对象 需要从JobRunner.java中删除以下代码: 该代码必须重新写入WhatsTimeConfiguration.java,下面是它现在的样子:
@Configuration
@ComponentScan(basePackages = "com.djordje.cleanarchitecture")
public class WhatsTheTimeConfiguration {
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setTriggers(trigger());
schedulerFactoryBean.setJobDetails(jobDetail());
schedulerFactoryBean.setJobFactory(springBeanJobFactory());
return schedulerFactoryBean;
}
@Bean
public SpringBeanJobFactory springBeanJobFactory() {
return new AutowiringSpringBeanJobFactory();
}
@Bean
public JobDetail jobDetail() {
JobDetailImpl jobDetail = new JobDetailImpl();
jobDetail.setKey(new JobKey("WhatsTheTime"));
jobDetail.setJobClass(WhatsTheTimeManager.class);
jobDetail.setDurability(true);
return jobDetail;
}
@Bean
public SimpleTrigger trigger() {
return newTrigger()
.forJob(jobDetail())
.withIdentity("whatsTheTimeJobTrigger", "jobsGroup1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(1)
.repeatForever())
.build();
}
}
SchedulerFactoryBean现在是一个Bean,将由Spring处理和初始化,SimpleRigger和AutowiringSpringBeanJobFactory也是如此
我添加了缺失的JobDetail类,该类缺失了,并向SimpleTrigger和SchedulerFactoryBean添加了必要的连接。他们都需要知道JobDetail,JobDetail是唯一知道需要触发的job类的地方。不确定您的意思是什么?非常感谢。是的,完全有道理。它现在工作得很好。。。回答得很好。
public interface TimeRetriever {
String timeFor(String location);
}
@Component
public class LocationRetrieverDataProvider implements LocationRetriever{
public LocationRetrieverDataProvider() {
}
@Override
public List<String> allLocations() {
return asList("Europe/London", "Europe/Madrid", "Europe/Moscow", "Asia/Tokyo", "Australia/Melbourne", "America/New_York");
}
}
@Component
public class TimeOutputRendererDataProvider implements TimeOutputRenderer {
public TimeOutputRendererDataProvider() {
}
@Override
public TimeReport renderReport(String location, String time) {
System.out.println(location + " time is " + time);
return new TimeReport(location, time);
}
}
@Component
public class TimeRetrieverDataProvider implements TimeRetriever {
public TimeRetrieverDataProvider() {
}
@Override
public String timeFor(String location) {
SimpleDateFormat timeInLocation = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
timeInLocation.setTimeZone(TimeZone.getTimeZone(location));
return timeInLocation.format(new Date());
}
}
SpringBeanJobFactory springBeanJobFactory = new SpringBeanJobFactory();
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setTriggers(trigger());
schedulerFactoryBean.setJobFactory(springBeanJobFactory);
schedulerFactoryBean.start();
...
private static SimpleTrigger trigger() {
return newTrigger()
.withIdentity("whatsTheTimeJobTrigger", "jobsGroup1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(1)
.repeatForever())
.build();
}
@Configuration
@ComponentScan(basePackages = "com.djordje.cleanarchitecture")
public class WhatsTheTimeConfiguration {
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setTriggers(trigger());
schedulerFactoryBean.setJobDetails(jobDetail());
schedulerFactoryBean.setJobFactory(springBeanJobFactory());
return schedulerFactoryBean;
}
@Bean
public SpringBeanJobFactory springBeanJobFactory() {
return new AutowiringSpringBeanJobFactory();
}
@Bean
public JobDetail jobDetail() {
JobDetailImpl jobDetail = new JobDetailImpl();
jobDetail.setKey(new JobKey("WhatsTheTime"));
jobDetail.setJobClass(WhatsTheTimeManager.class);
jobDetail.setDurability(true);
return jobDetail;
}
@Bean
public SimpleTrigger trigger() {
return newTrigger()
.forJob(jobDetail())
.withIdentity("whatsTheTimeJobTrigger", "jobsGroup1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(1)
.repeatForever())
.build();
}
}