2017-12-06 2 views
0

쿼츠를 사용하여 특정 시간에 특정 작업을 실행하려는 스프링 부트 프로젝트가 있습니다.스프링 쿼츠 상위 클래스 생성자를 사용하여 생성자 기반 주입 설정

2017-12-06 14:18:01,383 ERROR --- [quartz-jobs] org.quartz.core.ErrorLogger                : An error occured instantiating job to be executed. job= 'jobGroup.someJob' 
org.quartz.SchedulerException: Job instantiation failed 
    at org.springframework.scheduling.quartz.AdaptableJobFactory.newJob(AdaptableJobFactory.java:45) 
    at org.quartz.core.JobRunShell.initialize(JobRunShell.java:127) 
    at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:375) 
Caused by: java.lang.InstantiationException: com.jobs.SomeJob 
    at java.lang.Class.newInstance(Class.java:427) 
    at org.springframework.scheduling.quartz.AdaptableJobFactory.createJobInstance(AdaptableJobFactory.java:58) 
    at org.springframework.scheduling.quartz.SpringBeanJobFactory.createJobInstance(SpringBeanJobFactory.java:74) 
    at com.config.AutowiringSpringBeanJobFactory.createJobInstance(AutowiringSpringBeanJobFactory.java:27) 
    at org.springframework.scheduling.quartz.AdaptableJobFactory.newJob(AdaptableJobFactory.java:41) 
    ... 2 common frames omitted 
Caused by: java.lang.NoSuchMethodException: com.jobs.SomeJob.<init>() 
    at java.lang.Class.getConstructor0(Class.java:3082) 
    at java.lang.Class.newInstance(Class.java:412) 
    ... 6 common frames omitted 

내가 이미 같은 자동으로 묶어 공장이 있습니다 :

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; 
    } 
} 

을 그리고 나는 다음과 같은 오류가이 작업을 실행할 때, 그러나

abstract public class AbstractFoo { 
    protected final FooB fooB; 

    public AbstractFoo(FooB fooB) { 
     this.fooB = fooB; 
    } 
} 

@Service 
public class SomeJob extends AbstractFoo implements Job { 
    public SomeJob(FooB fooB) { 
     super(fooB); 
    } 

    @Override 
    public void execute(final JobExecutionContext context) throws JobExecutionException { 
     //do stuff 
    } 
} 

:이 클래스의 레이아웃을 여기 내 석영 구성 :

@Configuration 
public class QuartzConfig { 
    @Autowired 
    private DataSource dataSource; 
    @Autowired 
    private PlatformTransactionManager transactionManager; 
    @Autowired 
    private ApplicationContext applicationContext; 

    @Bean 
    public SchedulerFactoryBean quartzScheduler() { 
     SchedulerFactoryBean quartzScheduler = new SchedulerFactoryBean(); 

     quartzScheduler.setDataSource(dataSource); 
     quartzScheduler.setTransactionManager(transactionManager); 
     quartzScheduler.setOverwriteExistingJobs(true); 
     quartzScheduler.setSchedulerName("quartz-jobs"); 

     AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory(); 
     jobFactory.setApplicationContext(applicationContext); 
     quartzScheduler.setJobFactory(jobFactory); 

     quartzScheduler.setQuartzProperties(quartzProperties()); 

     Trigger[] triggers = {someJobTrigger().getObject(); 
     quartzScheduler.setTriggers(triggers); 

     return quartzScheduler; 
    } 

    @Bean 
    public CronTriggerFactoryBean someJobTrigger() { 
     CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean(); 
     cronTriggerFactoryBean.setJobDetail(someJob().getObject()); 
     cronTriggerFactoryBean.setCronExpression(cronExp); 
     cronTriggerFactoryBean.setGroup(someGroup); 
     return cronTriggerFactoryBean; 
    } 

    @Bean 
    public JobDetailFactoryBean someJob() { 
     JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean(); 
     jobDetailFactory.setJobClass(SomeJob.class); 
     jobDetailFactory.setGroup(someGroup); 
     jobDetailFactory.setDurability(true); 
     return jobDetailFactory; 
    } 

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

     return properties; 
    } 
} 

Quartz를 생성자를 통해 적절한 종속성에 연결되게하려면 어떻게해야합니까? docs에 명시된 바와 같이

+0

또한 spring-3.2.1 및 quartz-2.1.6을 사용하고 있는지 확인하십시오. 석영/스프링 –

+0

@RobertI에서 quartz-2.2, spring-boot-1.5.7 및 spring-4.3.4 – Richard

답변

0

:

One of the ramifications of this behavior is the fact that jobs must have a no-argument constructor (when using the default JobFactory implementation).

당신은 본질적를 autowiring 기능과 기본 JobFactory을 사용하여 추가했다. 개인 테스트에서 발견 한 사실은 autowiring이 생성자 주입과 작동하지 않는다는 것입니다. 또한 효과가 없으므로 Spring 주석 (Component, Service, e.c.t)으로 작업을 표시하지 마십시오.

문제를 해결하려면 작업을 리팩토링하여 기본 생성자를 사용하고 필드 주입과 관련된 종속성을 설정하십시오 (어쩌면 설정 주입도 가능).

abstract public class AbstractFoo { 
    @Autowired 
    protected FooB fooB; 
} 

public class SomeJob extends AbstractFoo implements Job { 

    @Override 
    public void execute(final JobExecutionContext context) throws JobExecutionException { 
     //do stuff 
    } 
} 
+0

을 사용하는 버전을 게시하지 않으면 오류가 발생하기 때문에 이것이 작동하지 않습니다.'Can not reference foo before supertype 생성자가 호출되었습니다. – Richard

+0

마지막 편집을 시도하십시오 – dev4Fun

+0

기본 클래스를 터치하고 싶지 않습니다. 많은 다른 클래스에 영향을 미치므로 – Richard

관련 문제