5

I am implement a Quartz job using a DAO service as below:

public class InitialFetchFrequenceScheduleJob implements Job
{
    @Autowired
    private FetchFrequencyService fetchFrequencyService;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException
    {
        try
        {
            List<FetchFrequency> frequencies = this.fetchFrequencyService.findAll(FetchFrequency.class);

The problem is, when call execute() method, the this.fetchFrequencyService.findAll(FetchFrequency.class); will throw NPE because fetchFrequenceService is null. I do anything wrong here? Any reply is much appreciated. Thank you!

P/s I am using Quartz 2.1.7

Update: This is FetchFrequencyServiceImpl:

@Service("fetchFrequencyService")
public class FetchFrequencyServiceImpl extends GenericDaoImpl implements FetchFrequencyService
{
}

Update: The code implement job:

JobDetail job = JobBuilder.newJob(InitialFetchFrequenceScheduleJob.class).build();
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MINUTE, 1);
        Trigger trigger = TriggerBuilder.newTrigger().forJob(job).startAt(cal.getTime()).build();
        Scheduler scheduler = new StdSchedulerFactory("quartz.properties").getScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);
skaffman
  • 398,947
  • 96
  • 818
  • 769
jack
  • 73
  • 1
  • 1
  • 12

4 Answers4

7

@Autowired will not work in a Quartz job implementation because it will not be instantiated by Spring. In order to get hold of Spring-managed beans in a Quartz job you should first of all use org.springframework.scheduling.quartz.SchedulerFactoryBean to manage the Quartz lifecycle. Using this FactoryBean you can specify the applicationContextSchedulerContextKey property to have a reference to the ApplicationContext supplied to your Quartz job in the scheduler context, e.g.:

<bean id="scheduler"
    class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="applicationContextSchedulerContextKey" value="applicationContext" />
    <!-- additional properties here -->
</bean>

You can now retrieve the ApplicationContext reference in your job, and then explicitly get the bean reference from the ApplicationContext:

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
    ApplicationContext applicationContext = (ApplicationContext) executionContext
               .getScheduler().getContext().get("applicationContext");

    FetchFrequencyService service = applicationContext.getBean(FetchFrequencyService.class);

    // Start using your service.
}
marthursson
  • 3,242
  • 1
  • 18
  • 28
  • Thanks, but I cannot find applicationContext.getBean() method. I am using spring 4.0.6 – jack Sep 08 '14 at 08:18
  • ApplicationContext.getBean is still present in 4.x (defined in interface BeanFactory, which is inherited by ApplicationContext). – marthursson Sep 08 '14 at 09:34
  • I did an edit on your code executionContext. It needs review from peer. You have JobExecutionContext context instead of JobExecutionContext executionContext – Marco Schoolenberg Jan 15 '16 at 03:21
  • @hfk: The edit is correct: the original code doesn't compile, since the parameter is named context but I'm referring to executionContext in the method body. – marthursson Jan 15 '16 at 13:03
1

The way you are using Quartz does not get Spring involved in the process at all, and therefor no wiring of dependencies takes place.

I suggest you take a look at this part of the official documentation for the basic info on how to integrate Spring with Quartz as well as this great SO answer

Community
  • 1
  • 1
geoand
  • 60,071
  • 24
  • 172
  • 190
  • thanks, but i want create Trigger dynamically not configure in xml file. – jack Sep 08 '14 at 09:59
  • @doxuannam Good point! I am sure you could hack your way around the code and get it to work with dynamic triggers as well – geoand Sep 08 '14 at 10:18
1

use :

SpringBeanAutowiringSupport.processInjectBasedOnCurrentContext(this)

to autowire your beans in your quartz job

M2E67
  • 937
  • 7
  • 23
-1

you have to annotate your classes with either of following annotation

for DAO

@Repository

service

@Service

controlloer

@Controller

so your service class should have below annotation.

@Service("fetchFrequencyService")
public Class FetchFrequencyService {
}

i thing you need to inject application context into SchedulerFactoryBean

<bean id="scheduler"
        class="org.springframework.scheduling.quartz.SchedulerFactoryBean"
        lazy-init="false">
        <property name="jobFactory">
            <bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory" />
        </property>
        <property name="applicationContextSchedulerContextKey">
            <value>applicationContext</value>
        </property>
</bean>
pappu_kutty
  • 2,378
  • 8
  • 49
  • 93