2017-12-06 6 views
0

Ich habe ein Spring-Boot-Projekt, das ich mit Quarz verwenden möchte, um bestimmte Jobs zu bestimmten Zeiten auszuführen. Ich habe diese Klasse Layout:Spring Quartz Constructor-basierte Injektion mit Konstruktor der Elternklasse einrichten

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

Allerdings, wenn ich diesen Job ich folgende Fehlermeldung erhalten, laufen:

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 

ich bereits eine autowire Fabrik haben etwa so:

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

Und Hier ist meine Quarzkonfiguration:

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

Wie bekomme ich Quartz über den Konstruktor in die entsprechenden Abhängigkeiten?

+0

Stellen Sie außerdem sicher, dass Sie Feder-3.2.1 und Quarz-2.1.6 verwenden. Wenn nicht post, welche Version Sie von Quarz/Feder verwenden –

+0

@Robert mit Quarz-2.2, Spring-Boot-1.5.7 und Feder-4.3.4 – Richard

Antwort

0

Wie in docs erklärte:

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

Sie im Wesentlichen hinzugefügt Standard JobFactory mit autowiring Fähigkeit verwenden. Was ich bei meinen persönlichen Tests herausgefunden habe, ist, dass Autowirfen mit der Konstruktorinjektion nicht funktioniert. Markieren Sie Ihren Job auch nicht mit Spring-Anmerkungen (Komponente, Service, e.c.t), da dies keine Auswirkungen hat.

Um Ihr Problem zu lösen, refaktorieren Sie Ihren Job so, dass er Standardkonstruktor- und Autowire-Abhängigkeiten mit Feldinjektion hat (vielleicht funktioniert auch die Setter-Injektion).

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

dies funktioniert nicht, weil ich den Fehler bekomme: 'Kann nicht foo vorher verweisen Supertype Konstruktor wurde aufgerufen – Richard

+0

Versuchen Sie meine letzte Bearbeitung – dev4Fun

+0

Ich möchte nicht die Basisklasse berühren, da es viele andere Klassen beeinflussen – Richard

Verwandte Themen