2017-09-26 51 views
3

我試着在春季使用石英調度器。當配置多個作業時,我會得到下面的異常彈簧引導不工作石英多個作業自動裝配

Job2中jobTrigger方法的參數0需要一個無法找到的'org.quartz.JobDetail'類型的bean。

石英 - V2.3,春 - V4.2.x的後續

配置類

@Configuration 
public class SchedulerConfig { 

private static final Logger LOG = LoggerFactory.getLogger(SchedulerConfig.class); 

@Autowired 
List<Trigger> triggers; 

@Bean 
public JobFactory jobFactory(ApplicationContext applicationContext) { 
    AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory(); 
    jobFactory.setApplicationContext(applicationContext); 
    return jobFactory; 
} 

@Bean 
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) throws IOException { 
    SchedulerFactoryBean factory = new SchedulerFactoryBean(); 
      factory.setAutoStartup(true); 
    factory.setJobFactory(jobFactory); 
     factory.setQuartzProperties(quartzProperties()); 
    if (triggers != null && !triggers.isEmpty()) { 
     LOG.info("starting jobs... Total Triggers - " + triggers.size()); 
     factory.setTriggers(triggers.toArray(new Trigger[triggers.size()])); 
    } 

    return factory; 
} 

@Bean 
public Properties quartzProperties() throws IOException { 
    PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); 
    propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties")); 
    propertiesFactoryBean.afterPropertiesSet(); 
    return propertiesFactoryBean.getObject(); 
} 


public static CronTriggerFactoryBean createCronTrigger(JobDetail jobDetail, String cronExpression) { 
    CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean(); 
    factoryBean.setJobDetail(jobDetail); 
    factoryBean.setCronExpression(cronExpression); 
    factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW); 
    return factoryBean; 
} 

public static JobDetailFactoryBean createJobDetail(Class jobClass) { 
    JobDetailFactoryBean factoryBean = new JobDetailFactoryBean(); 
    factoryBean.setJobClass(jobClass); 
    factoryBean.setDurability(true); 
    return factoryBean; 
} 

SpringBeanJobFactory

public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware { 

private static final Logger LOG = LoggerFactory.getLogger(AutowiringSpringBeanJobFactory.class); 

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); 
    LOG.info("create job instance"); 
    beanFactory.autowireBean(job); 
    return job; 
} 

}

作業1

@Component 
@DisallowConcurrentExecution 
public class Job1 implements Job { 

private final Logger log = LoggerFactory.getLogger(this.getClass()); 

@Value("${schedule}") 
private String frequency; 

@Autowired 
private Service service; 

@Override 
public void execute(JobExecutionContext jobExecutionContext) { 
    log.info("execute"); 
} 

@Bean(name = "jobBean1") 
public JobDetailFactoryBean job() { 
    return SchedulerConfig.createJobDetail(this.getClass()); 
} 

@Bean(name = "jobBean1Trigger") 
public CronTriggerFactoryBean jobTrigger(@Qualifier("jobBean1")JobDetail jobDetail) { 
    return SchedulerConfig.createCronTrigger(jobDetail, frequency); 
} 

工作2

@Component 
@DisallowConcurrentExecution 
public class Job2 implements Job { 

private final Logger log = LoggerFactory.getLogger(this.getClass()); 

@Value("${schedule}") 
private String frequency; 

@Autowired 
private Service service; 

@Override 
public void execute(JobExecutionContext jobExecutionContext) { 
    log.info("execute"); 
} 

@Bean(name = "jobBean2") 
public JobDetailFactoryBean job() { 
    return SchedulerConfig.createJobDetail(this.getClass()); 
} 

@Bean(name = "jobBean2Trigger") 
public CronTriggerFactoryBean jobTrigger(@Qualifier("jobBean2")JobDetail jobDetail) { 
    return SchedulerConfig.createCronTrigger(jobDetail, frequency); 
} 

的服務類有春天JPA回購。 問題的根本原因是以下自動佈線服務。如果我從兩個作業中刪除下面的自動佈線服務,那麼它工作正常。

@Autowired private service service;

如果這個autowired bean只有一個作業,那麼沒有例外。 如何使用相同的自動裝配依賴關係配置多個作業? 是什麼原因造成這個問題?

回答

0

jobTrigger方法期望作爲參數a JobDetail但傳遞的豆類型爲JobDetailFactoryBean

也許你應該做出以下改變或類似的東西。

@Bean(name = "jobBean1") 
public JobDetail job() { 
    return SchedulerConfig.createJobDetail(this.getClass()).getObject(); 
} 

和job2一樣。

順便提一下, 你提到Spring - v1.5。你真的使用哪個版本的Spring?

+0

「JobDetailFactoryBean提供豆式的用法配置的JobDetail實例」從http: //www.baeldung.com/spring-quartz-schedule。我的糟糕的春天版本是4.2.9 – Zire

+0

是的,但是你正試圖將'JobDetailFactoryBean' bean注入類型爲'JobDetail'的參數。這怎麼可能工作?我認爲你應該使用'JobDetailFactoryBean'的getObject()方法得到實際的jobDetail。 – lzagkaretos

+0

我猜春天手柄。如果不是,它甚至不適用於單一工作。我只有在有多個工作時纔會遇到問題。我可以在網上找到的所有文檔和文章都使用相同的方式。如果我刪除autowired服務,並使用應用程序上下文手動注入bean,我不明白這個問題。 – Zire

0

您試圖在Spring 4.2中使用spring引導配置。

嘗試改變工作類中的下列方法如下

@Bean(name = "jobBean1") 
public JobDetail job() { 
    return SchedulerConfig.createJobDetail(this.getClass()).getObject(); 
} 

@Bean(name = "jobBean1Trigger") 
public CronTrigger jobTrigger(@Qualifier("jobBean1")JobDetail jobDetail) { 
    return SchedulerConfig.createCronTrigger(jobDetail, frequency).getObject(); 
} 

而且採用彈簧4.3,因爲你需要

@Autowired 
List<Trigger> triggers; 

我相信集自動裝配工作只在4.3

0

我所面臨的同樣的問題,並經過一番努力後,我能夠解決它。它可能是在作業類中使用的註釋中實現的。我看到你正在使用@Component,就像我的情況一樣。相反,石英調度程序配置使用@Configuration標記進行註釋。

解決方案是使用@Configuration標籤標記作業。我的猜測是@Bean@Component構造的註釋類不完整構造/映射在@Configuration註釋的初始化階段。

1

這是您引用的用於在一個配置文件中處理多個Quartz作業的http://www.baeldung.com/spring-quartz-schedule的修改版本。爲了簡便起見,我沒有包括整個QrtzSheduler類只是調度方法更換和觸發器中使用@Qualifier參考:

... 
@Bean 
public Scheduler scheduler(Map<String, JobDetail> jobMap, Set<? extends Trigger> triggers) throws SchedulerException, IOException { 

    StdSchedulerFactory factory = new StdSchedulerFactory(); 
    factory.initialize(new ClassPathResource("quartz.properties").getInputStream()); 

    logger.debug("Getting a handle to the Scheduler"); 
    Scheduler scheduler = factory.getScheduler(); 
    scheduler.setJobFactory(springBeanJobFactory()); 
    Map<JobDetail,Set<? extends Trigger>> triggersAndJobs = new HashMap<JobDetail,Set<? extends Trigger>>; 
    for(JobDetail jobDetail : jobMap.getValues()){ 
     for(Trigger trigger : triggers){ 
      if(trigger.getJobKey().equals(jobDetail.getKey())){ 
       Set<Trigger> set = new HashSet<>(); 
       set.add(trigger); 
       triggerAndJobs.put(jobDetail,set); 
      } 
     } 
    } 
    scheduler.scheduleJobs(triggersAndJobs, false); 

    logger.debug("Starting Scheduler threads"); 
    scheduler.start(); 
    return scheduler; 
} 

@Bean(name="jobOne") 
public JobDetail jobDetailOne() { 

    ... 
} 

@Bean(name="jobTwo") 
public JobDetail jobDetailTwo() { 

    ... 
} 

@Bean 
public Trigger triggerOne(@Qualifier("jobOne")JobDetail jobDetail) { 

    ... 
} 

@Bean 
public Trigger triggerTwo(@Qualifier("jobTwo")JobDetail jobDetail) { 

    ... 
} 
+0

這正是我所需要的。非常感謝! – rocotocloc