inserire il riferimento del bean in un lavoro al quarzo in spring?

Sono riuscito a configurare e pianificare un lavoro Quartz utilizzando lo store persistente di JobStoreTX in spring. Non uso i lavori di Spring Quartz, perché ho bisogno di programmarli dynamicmente, in fase di esecuzione, e tutti gli esempi di integrazione di Spring with Quartz che ho trovato erano hard-coding degli shcedules nei file di configurazione di Spring … Comunque, ecco come Pianifico il lavoro:

JobDetail emailJob = JobBuilder.newJob(EMailJob.class) .withIdentity("someJobKey", "immediateEmailsGroup") .storeDurably() .build(); SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger() .withIdentity("someTriggerKey", "immediateEmailsGroup") .startAt(fireTime) .build(); // pass initialization parameters into the job emailJob.getJobDataMap().put(NotificationConstants.MESSAGE_PARAMETERS_KEY, messageParameters); emailJob.getJobDataMap().put(NotificationConstants.RECIPIENT_KEY, recipient); if (!scheduler.checkExists(jobKey) && scheduler.getTrigger(triggerKey) != null) { // schedule the job to run Date scheduleTime1 = scheduler.scheduleJob(emailJob, trigger); } 

EMailJob è un lavoro semplice che sta inviando e-mail usando la class JavaMailSenderImpl di Spring.

 public class EMailJob implements Job { @Autowired private JavaMailSenderImpl mailSenderImpl; public EMailJob() { } public void execute(JobExecutionContext context) throws JobExecutionException { .... try { mailSenderImpl.send(mimeMessage); } catch (MessagingException e) { .... throw new JobExecutionException("EMailJob failed: " + jobKey.getName(), e); } logger.info("EMailJob finished OK"); } 

Il problema è che ho bisogno di ottenere un riferimento a un’istanza di questa class (JavaMailSenderImpl) nella mia class EMailJob. Quando provo a iniettarlo in questo modo:

 @Autowired private JavaMailSenderImpl mailSenderImpl; 

non viene iniettato – il riferimento è NULL. Suppongo che stia succedendo perché non è Spring che crea un’istanza della class EMailJob, ma Quartz e Quartz non sanno nulla dell’iniezione di dipendenza …

Quindi, c’è un modo per forzare questa iniezione ad accadere?

Grazie!

Aggiornamento 1: @Aaron: qui è una parte rilevante dello stacktrace dall’avvio, che mostra che l’EMailJob è stato istanziato due volte:

 2011-08-15 14:16:38,687 [main] INFO org.springframework.context.support.GenericApplicationContext - Bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler#0' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2011-08-15 14:16:38,734 [main] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.s[email protected]1328c7a: defining beans [...]; root of factory hierarchy 2011-08-15 14:16:39,734 [main] INFO com.cambridgedata.notifications.EMailJob - EMailJob() - initializing ... 2011-08-15 14:16:39,937 [main] INFO org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor - Validated configuration attributes 2011-08-15 14:16:40,078 [main] INFO org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Validated configuration attributes 2011-08-15 14:16:40,296 [main] INFO org.springframework.jdbc.datasource.init.ResourceDatabasePopulator - Executing SQL script from class path resource ... 2011-08-15 14:17:14,031 [main] INFO com.mchange.v2.log.MLog - MLog clients using log4j logging. 2011-08-15 14:17:14,109 [main] INFO com.mchange.v2.c3p0.C3P0Registry - Initializing c3p0-0.9.1.1 [built 15-March-2007 01:32:31; debug? true; trace: 10] 2011-08-15 14:17:14,171 [main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl 2011-08-15 14:17:14,171 [main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.0.1 created. 2011-08-15 14:17:14,187 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Using thread monitor-based data access locking (synchronization). 2011-08-15 14:17:14,187 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - JobStoreTX initialized. 2011-08-15 14:17:14,187 [main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.0.1) 'NotificationsScheduler' with instanceId 'NON_CLUSTERED' Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads. Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is not clustered. 2011-08-15 14:17:14,187 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'NotificationsScheduler' initialized from the specified file : 'spring/quartz.properties' from the class resource path. 2011-08-15 14:17:14,187 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.0.1 2011-08-15 14:17:14,234 [main] INFO com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 2sajb28h1lcabf28k3nr1|13af084, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 2sajb28h1lcabf28k3nr1|13af084, idleConnectionTestPeriod -> 50, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/2010rewrite2, lastAcquisitionFailureDefaultUser -> null, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 5, maxStatements -> 0, maxStatementsPerConnection -> 120, minPoolSize -> 1, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> select 0 from dual, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> true, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ] 2011-08-15 14:17:14,312 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Freed 0 triggers from 'acquired' / 'blocked' state. 2011-08-15 14:17:14,328 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Recovering 0 jobs that were in-progress at the time of the last shut-down. 2011-08-15 14:17:14,328 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Recovery complete. 2011-08-15 14:17:14,328 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Removed 0 'complete' triggers. 2011-08-15 14:17:14,328 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Removed 0 stale fired job entries. 2011-08-15 14:17:14,328 [main] INFO org.quartz.core.QuartzScheduler - Scheduler NotificationsScheduler_$_NON_CLUSTERED started. 2011-08-15 14:17:14,515 [NotificationsScheduler_QuartzSchedulerThread] INFO com.cambridgedata.notifications.EMailJob - EMailJob() - initializing ... 

Grazie!

Aggiornamento n. 2: @Ryan:

Ho provato a usare lo SpringBeanJobFactory come segue:

        

E ho modificato la mia class principale per ottenere Scheduler da questa fabbrica, invece di Quartz ‘:

  @PostConstruct public void initNotificationScheduler() { try { //sf = new StdSchedulerFactory("spring/quartz.properties"); //scheduler = sf.getScheduler(); scheduler = schedulerFactoryBean.getScheduler(); scheduler.start(); .... 

Ma quando eseguo l’app: ottieni errori, vedi sotto. Ecco lo stacktrace dall’avvio di Spring. Sembra che lo Scheduler stesso sia stato creato correttamente, ma l’errore si verifica quando sta tentando di creare un’istanza del mio EMailJob:

 2011-08-15 21:49:42,968 [main] INFO org.springframework.scheduling.quartz.SchedulerFactoryBean - Loading Quartz config from [class path resource [spring/quartz.properties]] 2011-08-15 21:49:43,031 [main] INFO com.mchange.v2.log.MLog - MLog clients using log4j logging. 2011-08-15 21:49:43,109 [main] INFO com.mchange.v2.c3p0.C3P0Registry - Initializing c3p0-0.9.1.1 [built 15-March-2007 01:32:31; debug? true; trace: 10] 2011-08-15 21:49:43,187 [main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl 2011-08-15 21:49:43,187 [main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.0.1 created. 2011-08-15 21:49:43,187 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Using thread monitor-based data access locking (synchronization). 2011-08-15 21:49:43,187 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - JobStoreTX initialized. 2011-08-15 21:49:43,187 [main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.0.1) 'schedulerFactoryBean' with instanceId 'NON_CLUSTERED' Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads. Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is not clustered. 2011-08-15 21:49:43,187 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'schedulerFactoryBean' initialized from an externally provided properties instance. 2011-08-15 21:49:43,187 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.0.1 2011-08-15 21:49:43,187 [main] INFO org.quartz.core.QuartzScheduler - JobFactory set to: [email protected]3 2011-08-15 21:49:43,265 [main] INFO com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hge13f8h1lsg7py1rg0iu0|1956391, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hge13f8h1lsg7py1rg0iu0|1956391, idleConnectionTestPeriod -> 50, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/2010rewrite2, lastAcquisitionFailureDefaultUser -> null, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 5, maxStatements -> 0, maxStatementsPerConnection -> 120, minPoolSize -> 1, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> select 0 from dual, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> true, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ] 2011-08-15 21:49:43,343 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Freed 0 triggers from 'acquired' / 'blocked' state. 2011-08-15 21:49:43,359 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Recovering 0 jobs that were in-progress at the time of the last shut-down. 2011-08-15 21:49:43,359 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Recovery complete. 2011-08-15 21:49:43,359 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Removed 0 'complete' triggers. 2011-08-15 21:49:43,359 [main] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Removed 0 stale fired job entries. 2011-08-15 21:49:43,359 [main] INFO org.quartz.core.QuartzScheduler - Scheduler schedulerFactoryBean_$_NON_CLUSTERED started. 2011-08-15 21:49:43,562 [schedulerFactoryBean_QuartzSchedulerThread] ERROR org.quartz.core.ErrorLogger - An error occured instantiating job to be executed. job= 'immediateEmailsGroup.DEFAULT.jobFor_1000new1' org.quartz.SchedulerException: Problem instantiating class 'com.cambridgedata.notifications.EMailJob' - [See nested exception: java.lang.AbstractMethodError: org.springframework.scheduling.quartz.SpringBeanJobFactory.newJob(Lorg/quartz/spi/TriggerFiredBundle;Lorg/quartz/Scheduler;)Lorg/quartz/Job;] at org.quartz.core.JobRunShell.initialize(JobRunShell.java:141) at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:381) Caused by: java.lang.AbstractMethodError: org.springframework.scheduling.quartz.SpringBeanJobFactory.newJob(Lorg/quartz/spi/TriggerFiredBundle;Lorg/quartz/Scheduler;)Lorg/quartz/Job; at org.quartz.core.JobRunShell.initialize(JobRunShell.java:134) 

Grazie!

Solo un riepilogo della soluzione fornita da jelies e un paio di altre cose per rendere più semplice l’integrazione con Spring + Quartz: http://codrspace.com/Khovansa/spring-quartz-with-a-database/

È ansible utilizzare questo object SpringBeanJobFactory per eseguire automaticamente il salvataggio degli oggetti del quarzo utilizzando la molla:

 import org.quartz.spi.TriggerFiredBundle; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.scheduling.quartz.SpringBeanJobFactory; 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; } } 

Quindi, collegalo al tuo SchedulerBean (in questo caso, con Java-config):

 @Bean public SchedulerFactoryBean quartzScheduler() { SchedulerFactoryBean quartzScheduler = new SchedulerFactoryBean(); ... AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory(); jobFactory.setApplicationContext(applicationContext); quartzScheduler.setJobFactory(jobFactory); ... return quartzScheduler; } 

Lavorando per me, usando spring-3.2.1 e quarzo-2.1.6.

Controlla l’essenza completa qui .

Ho trovato la soluzione in questo post del blog

Ho appena messo SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); come prima linea del mio Job.execute(JobExecutionContext context) .

Lo stesso problema è stato risolto in LINK :

Ho trovato altre opzioni da post sul forum Spring che è ansible passare un riferimento al contesto dell’applicazione Spring tramite SchedulerFactoryBean. Come nell’esempio mostrato di seguito:

        applicationContext  

Quindi, utilizzando il codice riportato di seguito nella propria class di lavoro, è ansible ottenere applicationContext e ottenere il bean desiderato.

 appCtx = (ApplicationContext)context.getScheduler().getContext().get("applicationContextSchedulerContextKey"); 

Spero che sia d’aiuto. Puoi ottenere maggiori informazioni da Mark Mclaren’sBlog

Hai ragione nel presupporre che Spring vs. Quartz instanzia la class. Tuttavia, Spring fornisce alcune classi che ti permettono di fare un’iniezione di dipendenza primitiva in Quartz. Controlla SchedulerFactoryBean.setJobFactory () insieme a SpringBeanJobFactory . In sostanza, utilizzando SpringBeanJobFactory, si abilita l’integrazione delle dipendenze su tutte le proprietà del lavoro, ma solo per i valori che si trovano nel contesto del programmatore Quartz o nella mappa dei dati del lavoro . Non so quali siano tutti gli stili DI che supporta (costruttore, annotazione, setter …) ma so che supporta l’iniezione setter.

per tutti quelli che proveranno questo in futuro.

org.springframework.scheduling.quartz.JobDetailBean fornisce una mappa degli oggetti e questi oggetti potrebbero essere fagioli primaverili.

definire smth come

         

e poi, dentro

 public void executeInternal(JobExecutionContext context) 

chiama myBean = (myBean) context.getMergedJobDataMap().get("myBean"); e voi tutti insieme. Lo so, sembra brutto, ma come soluzione funziona

 ApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(ContextLoaderListener .getCurrentWebApplicationContext().getServletContext()); Bean bean = (Bean) springContext.getBean("beanName"); bean.method(); 

Grazie, Rippon! Finalmente ho lavorato anch’io, dopo molte lotte, e la mia soluzione è molto vicina a ciò che mi hai suggerito! La chiave era di fare il mio lavoro per estendere QuartzJobBean e utilizzare la schedulerContextAsMap.

Sono partito senza specificare la proprietà applicationContextSchedulerContextKey – ha funzionato senza di esso per me.

Per il bene degli altri, ecco la configurazione finale che ha funzionato per me:

                                       

Si noti che il bean ‘mailService’ è il mio bean di servizio, gestito da Spring. Sono riuscito ad accedervi nel mio Job come segue:

  public void executeInternal(JobExecutionContext context) throws JobExecutionException { logger.info("EMailJob started ..."); .... SchedulerContext schedulerContext = null; try { schedulerContext = context.getScheduler().getContext(); } catch (SchedulerException e1) { e1.printStackTrace(); } MailService mailService = (MailService)schedulerContext.get("mailService"); .... 

E questa configurazione mi ha permesso anche di eseguire dynamicmente i lavori di pianificazione, utilizzando le fabbriche per ottenere Trigger e JobDetails e impostando i parametri richiesti su di essi a livello di programmazione:

  public NotificationScheduler(final Scheduler scheduler, final ObjectFactory jobDetailFactory, final ObjectFactory jobTriggerFactory) { this.scheduler = scheduler; this.jobDetailFactory = jobDetailFactory; this.jobTriggerFactory = jobTriggerFactory; ... // create a trigger SimpleTrigger trigger = jobTriggerFactory.getObject(); trigger.setRepeatInterval(0L); trigger.setStartTime(new Date()); // create job details JobDetail emailJob = jobDetailFactory.getObject(); emailJob.setName("new name"); emailJob.setGroup("immediateEmailsGroup"); ... 

Grazie mille a tutti coloro che hanno aiutato,

Marina

Ecco come appare il codice con @Component:

Classe principale che pianifica il lavoro:

 public class NotificationScheduler { private SchedulerFactory sf; private Scheduler scheduler; @PostConstruct public void initNotificationScheduler() { try { sf = new StdSchedulerFactory("spring/quartz.properties"); scheduler = sf.getScheduler(); scheduler.start(); // test out sending a notification at startup, prepare some parameters... this.scheduleImmediateNotificationJob(messageParameters, recipients); try { // wait 20 seconds to show jobs logger.info("sleeping..."); Thread.sleep(40L * 1000L); logger.info("finished sleeping"); // executing... } catch (Exception ignore) { } } catch (SchedulerException e) { e.printStackTrace(); throw new RuntimeException("NotificationScheduler failed to retrieve a Scheduler instance: ", e); } } public void scheduleImmediateNotificationJob(){ try { JobKey jobKey = new JobKey("key"); Date fireTime = DateBuilder.futureDate(delayInSeconds, IntervalUnit.SECOND); JobDetail emailJob = JobBuilder.newJob(EMailJob.class) .withIdentity(jobKey.toString(), "immediateEmailsGroup") .build(); TriggerKey triggerKey = new TriggerKey("triggerKey"); SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger() .withIdentity(triggerKey.toString(), "immediateEmailsGroup") .startAt(fireTime) .build(); // schedule the job to run Date scheduleTime1 = scheduler.scheduleJob(emailJob, trigger); } catch (SchedulerException e) { logger.error("error scheduling job: " + e.getMessage(), e); e.printStackTrace(); } } @PreDestroy public void cleanup(){ sf = null; try { scheduler.shutdown(); } catch (SchedulerException e) { e.printStackTrace(); } } 

EmailJob è lo stesso del mio primo post eccetto l’annotazione @Component:

 @Component public class EMailJob implements Job { @Autowired private JavaMailSenderImpl mailSenderImpl; ... } 

E il file di configurazione di Spring ha:

 ...         ...    

Grazie per tutto l’aiuto!

Marina

Una soluzione semplice consiste nell’impostare il bean spring nella Job Data Map e quindi nel recuperare il bean nella class di lavoro, ad esempio

 // the class sets the configures the MyJob class SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sched = sf.getScheduler(); Date startTime = DateBuilder.nextGivenSecondDate(null, 15); JobDetail job = newJob(MyJob.class).withIdentity("job1", "group1").build(); job.getJobDataMap().put("processDataDAO", processDataDAO); 

`

  // this is MyJob Class ProcessDataDAO processDataDAO = (ProcessDataDAO) jec.getMergedJobDataMap().get("processDataDAO"); 

Una soluzione di Hary https://stackoverflow.com/a/37797575/4252764 funziona molto bene. È più semplice, non ha bisogno di tanti bean factory speciali e supporta più trigger e processi. Vorrei solo aggiungere che il lavoro Quartz può essere fatto per essere generico, con lavori specifici implementati come regolari Spring bean.

 public interface BeanJob { void executeBeanJob(); } public class GenericJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap dataMap = context.getMergedJobDataMap(); ((BeanJob)dataMap.get("beanJob")).executeBeanJob(); } } @Component public class RealJob implements BeanJob { private SomeService service; @Autowired public RealJob(SomeService service) { this.service = service; } @Override public void executeBeanJob() { //do do job with service } } 

Un modo semplice per farlo sarebbe semplicemente annotare i Lavori al quarzo con @Component annotazione @Component , e quindi Spring eseguirà tutte le magie DI per te, poiché ora è riconosciuto come bean Spring. Ho dovuto fare qualcosa di simile per un aspetto AspectJ – non era un bean Spring finché non l’ho annotato con lo stereotipo di Spring @Component .

Assicurati il ​​tuo

 AutowiringSpringBeanJobFactory extends SpringBeanJobFactory 

la dipendenza viene tirata da

  "org.springframework:spring-context-support:4..." 

e NON da

  "org.springframework:spring-support:2..." 

Voleva che lo usassi

 @Override public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) 

invece di

 @Override protected Object createJobInstance(final TriggerFiredBundle bundle) 

quindi non riusciva a scovare istanza di lavoro.

Quando si utilizza già AspectJ reale nel progetto, è ansible annotare la class del bean di lavoro con @Configurable . Quindi la spring verrà iniettata in questa class, anche se è costruita per la prima volta

Ho affrontato il problema simile e ne sono uscito con il seguente approccio:

            

Nel codice precedente ho iniettato dao.DAOFramework bean in JobA bean e all’interno del metodo ExecuteInternal puoi ottenere bean iniettato come:

  daoFramework = (DAOFramework)context.getMergedJobDataMap().get("daoBean"); 

Spero possa essere d’aiuto! Grazie.

La soluzione sopra è ottima ma nel mio caso l’iniezione non funzionava. Avevo bisogno di usare autowireBeanProperties invece, probabilmente a causa del modo in cui è configurato il mio contesto:

 import org.quartz.spi.TriggerFiredBundle; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.scheduling.quartz.SpringBeanJobFactory; 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); beanFactory.autowireBeanProperties(job, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true); return job; } } 

This is the right answer http://stackoverflow.com/questions/6990767/inject-bean-reference-into-a-quartz-job-in-spring/15211030#15211030 . and will work for most of the folks. But if your web.xml does is not aware of all applicationContext.xml files, quartz job will not be able to invoke those beans. I had to do an extra layer to inject additional applicationContext files

 public class MYSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware { private transient AutowireCapableBeanFactory beanFactory; @Override public void setApplicationContext(final ApplicationContext context) { try { PathMatchingResourcePatternResolver pmrl = new PathMatchingResourcePatternResolver(context.getClassLoader()); Resource[] resources = new Resource[0]; GenericApplicationContext createdContext = null ; resources = pmrl.getResources( "classpath*:my-abc-integration-applicationContext.xml" ); for (Resource r : resources) { createdContext = new GenericApplicationContext(context); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(createdContext); int i = reader.loadBeanDefinitions(r); } createdContext.refresh();//important else you will get exceptions. beanFactory = createdContext.getAutowireCapableBeanFactory(); } catch (IOException e) { e.printStackTrace(); } } @Override protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { final Object job = super.createJobInstance(bundle); beanFactory.autowireBean(job); return job; } } 

You can add any number of context files you want your quartz to be aware of.

This is a quite an old post which is still useful. All the solutions that proposes these two had little condition that not suite all:

  • SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); This assumes or requires it to be a spring – web based project
  • AutowiringSpringBeanJobFactory based approach mentioned in previous answer is very helpful, but the answer is specific to those who don’t use pure vanilla quartz api but rather Spring’s wrapper for the quartz to do the same.

If you want to remain with pure Quartz implementation for scheduling(Quartz with Autowiring capabilities with Spring), I was able to do it as follows:

I was looking to do it quartz way as much as possible and thus little hack proves helpful.

  public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory{ private AutowireCapableBeanFactory beanFactory; public AutowiringSpringBeanJobFactory(final ApplicationContext applicationContext){ beanFactory = applicationContext.getAutowireCapableBeanFactory(); } @Override protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { final Object job = super.createJobInstance(bundle); beanFactory.autowireBean(job); beanFactory.initializeBean(job, job.getClass().getName()); return job; } } @Configuration public class SchedulerConfig { @Autowired private ApplicationContext applicationContext; @Bean public AutowiringSpringBeanJobFactory getAutowiringSpringBeanJobFactory(){ return new AutowiringSpringBeanJobFactory(applicationContext); } } private void initializeAndStartScheduler(final Properties quartzProperties) throws SchedulerException { //schedulerFactory.initialize(quartzProperties); Scheduler quartzScheduler = schedulerFactory.getScheduler(); //Below one is the key here. Use the spring autowire capable job factory and inject here quartzScheduler.setJobFactory(autowiringSpringBeanJobFactory); quartzScheduler.start(); } 

quartzScheduler.setJobFactory(autowiringSpringBeanJobFactory); gives us an autowired job instance. Since AutowiringSpringBeanJobFactory implicitly implements a JobFactory , we now enabled an auto-wireable solution. Spero che questo ti aiuti!

All those solutions above doesn’t work for me with Spring 5 and Hibernate 5 and Quartz 2.2.3 when I want to call transactional methods!

I therefore implemented this solution which automatically starts the scheduler and triggers the jobs. I found a lot of that code at dzone . Because I don’t need to create triggers and jobs dynamically I wanted the static triggers to be pre defined via Spring Configuration and only the jobs to be exposed as Spring Components.

My basic configuration look like this

 @Configuration public class QuartzConfiguration { @Autowired ApplicationContext applicationContext; @Bean public SchedulerFactoryBean scheduler(@Autowired JobFactory jobFactory) throws IOException { SchedulerFactoryBean sfb = new SchedulerFactoryBean(); sfb.setOverwriteExistingJobs(true); sfb.setAutoStartup(true); sfb.setJobFactory(jobFactory); Trigger[] triggers = new Trigger[] { cronTriggerTest().getObject() }; sfb.setTriggers(triggers); return sfb; } @Bean public JobFactory cronJobFactory() { AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory(); jobFactory.setApplicationContext(applicationContext); return jobFactory; } @Bean public CronTriggerFactoryBean cronTriggerTest() { CronTriggerFactoryBean tfb = new CronTriggerFactoryBean(); tfb.setCronExpression("0 * * ? * * *"); JobDetail jobDetail = JobBuilder.newJob(CronTest.class) .withIdentity("Testjob") .build() ; tfb.setJobDetail(jobDetail); return tfb; } } 

As you can see, you have the scheduler and a simple test trigger which is defined via a cron expression. You can obviously choose whatever scheduling expression you like. You then need the AutowiringSpringBeanJobFactory which goes like this

 public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware { @Autowired private ApplicationContext applicationContext; private SchedulerContext schedulerContext; @Override public void setApplicationContext(final ApplicationContext context) { this.applicationContext = context; } @Override protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { Job job = applicationContext.getBean(bundle.getJobDetail().getJobClass()); BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.addPropertyValues(bundle.getJobDetail().getJobDataMap()); pvs.addPropertyValues(bundle.getTrigger().getJobDataMap()); if (this.schedulerContext != null) { pvs.addPropertyValues(this.schedulerContext); } bw.setPropertyValues(pvs, true); return job; } public void setSchedulerContext(SchedulerContext schedulerContext) { this.schedulerContext = schedulerContext; super.setSchedulerContext(schedulerContext); } } 

In here you wire your normal application context and your job together. This is the important gap because normally Quartz starts it’s worker threads which have no connection to your application context. That is the reason why you can’t execute Transactional mehtods. The last thing missing is a job. It can look like that

 @Component public class CronTest implements Job { @Autowired private MyService s; public CronTest() { } @Override public void execute(JobExecutionContext context) throws JobExecutionException { s.execute(); } } 

It’s not a perfect solution because you an extra class only for calling your service method. But nevertheless it works.