1

Quartz is creating new instance of the class through the JobBuilder each time

JobBuilder.newJob(MyJob.class)

However, I only want one MyJob instance, and only trigger testFunction from execute function, how can I make it work?

I find through QuartzGuiceLib I can use some annotations to make it happen, through Spring I can change something in configuration file. But how can I implement it by pure Java without any framwork?

Below is the code snapshot:

public class MyJob implements Job {
    public MyJob() {
        testFunction();

        try {
            final Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            if (!scheduler.checkExists(JOB_KEY)) {
                triggerScheduler(scheduler);
            } else {
                log.info("Job with key {{}} already exist", JOB_KEY);
            }
        } catch (SchedulerException e) {
            log.error("Fail to start scheduler", e);
        }
    }

    public void testFunction() {
    }

    private void triggerScheduler(final Scheduler scheduler) throws SchedulerException {
        final JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity(JOB_KEY)
                .build();

        final Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("myjob")
                .withSchedule(
                        simpleSchedule()
                                .withIntervalInSeconds(60)
                                .repeatForever())
                .build();

        scheduler.start();

        log.info("Scheduling job with key {{}}", jobDetail.getKey());

        scheduler.scheduleJob(jobDetail, trigger);
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        testFunction();
    }
}
TommyQu
  • 509
  • 5
  • 18
  • You might want to separate this into several classes. One for the actual job you want to run and another for the scheduler. This will make it so each class has one concern and make it much easier to read/debug. – randal4 Aug 17 '18 at 18:14

1 Answers1

2

It might be easier to keep the job and scheduler in two separate classes as below:

public class MyQuartzScheduler {
    public static void main( String[] args ) throws Exception {
        JobDetail job = JobBuilder.newJob(MyJob.class)
        .withIdentity("dummyJobName", "group1").build();

        Trigger trigger = TriggerBuilder
        .newTrigger()
        .withIdentity("MyJobTrigger", "group1")
        .withSchedule(
            CronScheduleBuilder.cronSchedule("0 * * * * ?"))
        .build();

        Scheduler scheduler = new StdSchedulerFactory().getScheduler();
        scheduler.start();
        scheduler.scheduleJob(job, trigger);
    }
}

And then your Job Class:

public class MyJob implements Job {    
    public void testFunction() {
        System.out.println("Running Test!");
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        testFunction();
    }
}

This is an adaptation taken from an mkyong tutorial article found at:

https://www.mkyong.com/java/quartz-2-scheduler-tutorial/

For the answer to your question though, Quartz does create a new instance per run: https://stackoverflow.com/a/10463309/1410671

You could make another static class or Factory that your Job class would call which would use the same instance every call.

public class MyJob implements Job {

    public void testFunction() {
        MyClassWithStaticCounter.increaseCounter(1);
        System.out.println(MyClassWithStaticCounter.getCounter());
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        testFunction();
    }
}

And your class that has the static stuff:

public class MyClassWithStaticCounter {
    private static int counter = 0;

    public static void increaseCounter(int i){
        counter += i;
    }

    public static int getCounter(){
        return counter;
    }
}
randal4
  • 590
  • 4
  • 16