title: inject bean reference into a Quartz job in Spring?
body: <p>I managed to configure and schedule a Quartz  job using JobStoreTX persistent store in Spring. I do not use Spring's Quartz jobs, because I need to schedule them dynamically, at run time, and all examples of integrating Spring with Quartz that i found were hard-coding the shcedules in the Spring config files... Anyway, here is how I schedule the job:</p>
  
  <pre><code>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) &amp;&amp; scheduler.getTrigger(triggerKey) != null)     {                                       
  // schedule the job to run
  Date scheduleTime1 = scheduler.scheduleJob(emailJob, trigger);
  }
  </code></pre>
  
  <p>The EMailJob is a simple job that is sending e-mail using the Spring's JavaMailSenderImpl class.</p>
  
  <pre><code>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");
  
  }
  </code></pre>
  
  <p>The problem is that I need to get a reference to an instance of this class (JavaMailSenderImpl)  in my EMailJob class. When I try to inject it like this:</p>
  
  <pre><code>@Autowired
  private JavaMailSenderImpl mailSenderImpl;
  </code></pre>
  
  <p>it is not injected - the reference is NULL. I'm assuming this is happening because it is not  Spring who instantiates the EMailJob class, but Quartz, and Quartz does not know anything about dependency injection...</p>
  
  <p>So, is there some way to force this injection to happen?</p>
  
  <p>thanks!</p>
  
  <p>Update 1:
  @Aaron:
  here is a relevant part of the stacktrace from the startup, which is showing the the EMailJob was instantiated twice:</p>
  
  <pre><code>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.springframework.beans.factory.support.DefaultListableBeanFactory@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 -&gt; 3, acquireRetryAttempts -&gt; 30, acquireRetryDelay -&gt; 1000, autoCommitOnClose -&gt; false, automaticTestTable -&gt; null, breakAfterAcquireFailure -&gt; false, checkoutTimeout -&gt; 0, connectionCustomizerClassName -&gt; null, connectionTesterClassName -&gt; com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -&gt; 2sajb28h1lcabf28k3nr1|13af084, debugUnreturnedConnectionStackTraces -&gt; false, description -&gt; null, driverClass -&gt; com.mysql.jdbc.Driver, factoryClassLocation -&gt; null, forceIgnoreUnresolvedTransactions -&gt; false, identityToken -&gt; 2sajb28h1lcabf28k3nr1|13af084, idleConnectionTestPeriod -&gt; 50, initialPoolSize -&gt; 3, jdbcUrl -&gt; jdbc:mysql://localhost:3306/2010rewrite2, lastAcquisitionFailureDefaultUser -&gt; null, maxAdministrativeTaskTime -&gt; 0, maxConnectionAge -&gt; 0, maxIdleTime -&gt; 0, maxIdleTimeExcessConnections -&gt; 0, maxPoolSize -&gt; 5, maxStatements -&gt; 0, maxStatementsPerConnection -&gt; 120, minPoolSize -&gt; 1, numHelperThreads -&gt; 3, numThreadsAwaitingCheckoutDefaultUser -&gt; 0, preferredTestQuery -&gt; select 0 from dual, properties -&gt; {user=******, password=******}, propertyCycle -&gt; 0, testConnectionOnCheckin -&gt; true, testConnectionOnCheckout -&gt; false, unreturnedConnectionTimeout -&gt; 0, usesTraditionalReflectiveProxies -&gt; 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 ...
  </code></pre>
  
  <p>thanks!</p>
  
  <p>Update #2: @Ryan:</p>
  
  <p>I tried to use the SpringBeanJobFactory as following:</p>
  
  <pre><code>    &lt;bean id="jobFactoryBean" class="org.springframework.scheduling.quartz.SpringBeanJobFactory"&gt;
  &lt;/bean&gt;
  
  &lt;bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"&gt;
          &lt;property name="configLocation" value="classpath:spring/quartz.properties"/&gt;
          &lt;property name="jobFactory" ref="jobFactoryBean"/&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p>And I have modified my main class to get Scheduler from this factory, instead of Quartz':</p>
  
  <pre><code>    @PostConstruct
  public void initNotificationScheduler() {
      try {
          //sf = new StdSchedulerFactory("spring/quartz.properties");
          //scheduler = sf.getScheduler();
  
          scheduler = schedulerFactoryBean.getScheduler();
          scheduler.start();
              ....
  </code></pre>
  
  <p>But when I run the app - get errors, see below. Here is the stacktrace from Spring startup . Seems like the Scheduler itself is created fine, but the error comes when it is trying to instantiate my EMailJob:</p>
  
  <pre><code>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: org.springframework.scheduling.quartz.SpringBeanJobFactory@566633
  2011-08-15 21:49:43,265 [main] INFO  com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -&gt; 3, acquireRetryAttempts -&gt; 30, acquireRetryDelay -&gt; 1000, autoCommitOnClose -&gt; false, automaticTestTable -&gt; null, breakAfterAcquireFailure -&gt; false, checkoutTimeout -&gt; 0, connectionCustomizerClassName -&gt; null, connectionTesterClassName -&gt; com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -&gt; 1hge13f8h1lsg7py1rg0iu0|1956391, debugUnreturnedConnectionStackTraces -&gt; false, description -&gt; null, driverClass -&gt; com.mysql.jdbc.Driver, factoryClassLocation -&gt; null, forceIgnoreUnresolvedTransactions -&gt; false, identityToken -&gt; 1hge13f8h1lsg7py1rg0iu0|1956391, idleConnectionTestPeriod -&gt; 50, initialPoolSize -&gt; 3, jdbcUrl -&gt; jdbc:mysql://localhost:3306/2010rewrite2, lastAcquisitionFailureDefaultUser -&gt; null, maxAdministrativeTaskTime -&gt; 0, maxConnectionAge -&gt; 0, maxIdleTime -&gt; 0, maxIdleTimeExcessConnections -&gt; 0, maxPoolSize -&gt; 5, maxStatements -&gt; 0, maxStatementsPerConnection -&gt; 120, minPoolSize -&gt; 1, numHelperThreads -&gt; 3, numThreadsAwaitingCheckoutDefaultUser -&gt; 0, preferredTestQuery -&gt; select 0 from dual, properties -&gt; {user=******, password=******}, propertyCycle -&gt; 0, testConnectionOnCheckin -&gt; true, testConnectionOnCheckout -&gt; false, unreturnedConnectionTimeout -&gt; 0, usesTraditionalReflectiveProxies -&gt; 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)
  </code></pre>
  
  <p>thanks!</p>