/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.terracotta.quartz.tests; import com.tc.test.config.model.TestConfig; import java.util.List; import java.util.concurrent.CyclicBarrier; import org.hamcrest.core.Is; import org.junit.Assert; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.PersistJobDataAfterExecution; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerMetaData; import org.quartz.Trigger; import org.quartz.spi.JobFactory; import org.quartz.spi.TriggerFiredBundle; import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger; /** * * @author cdennis */ public class PersistJobDataAfterExecutionTest extends AbstractStandaloneTest { private static final int NODE_COUNT = 2; public PersistJobDataAfterExecutionTest(TestConfig testConfig) { super(testConfig, PersistJobData1.class, PersistJobData2.class); testConfig.getClientConfig().setParallelClients(false); } public static class PersistJobData1 extends ClientBase { public PersistJobData1(String[] args) { super(args); } public static void main(String[] args) { new PersistJobData1(args).run(); } @Override protected void test(Scheduler scheduler) throws Throwable { final CyclicBarrier localBarrier = new CyclicBarrier(2); scheduler.setJobFactory(new JobFactory() { @Override public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException { JobDetail jobDetail = bundle.getJobDetail(); Class<? extends Job> jobClass = jobDetail.getJobClass(); try { return jobClass.getConstructor(CyclicBarrier.class).newInstance(localBarrier); } catch (Exception e) { throw new SchedulerException(e); } } }); JobDetail jobDetail = newJob(TestJob.class).withIdentity("job").build(); jobDetail.getJobDataMap().put("id", "job"); jobDetail.getJobDataMap().put(TestJob.JOB_PROP_NAME, 0); jobDetail.requestsRecovery(); Trigger trigger = newTrigger().withIdentity("trigger") .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(1)) .build(); scheduler.scheduleJob(jobDetail, trigger); // start node1's scheduler first to let it run some jobs, then switch to node2 JobDetail lastRunningJob = null; List<JobExecutionContext> contextList = null; scheduler.start(); localBarrier.await(); contextList = scheduler.getCurrentlyExecutingJobs(); Assert.assertEquals(contextList.size(), 1); lastRunningJob = contextList.get(0).getJobDetail(); localBarrier.await(); scheduler.shutdown(true); SchedulerMetaData metaData = scheduler.getMetaData(); int numJobsExecuted = metaData.getNumberOfJobsExecuted(); int finalCount = lastRunningJob.getJobDataMap().getIntValue(TestJob.JOB_PROP_NAME); Assert.assertThat(numJobsExecuted, Is.is(1)); Assert.assertThat(finalCount, Is.is(1)); } protected boolean isStartingScheduler() { return false; } } public static class PersistJobData2 extends ClientBase { public PersistJobData2(String[] args) { super(args); } public static void main(String[] args) { new PersistJobData1(args).run(); } @Override protected void test(Scheduler scheduler) throws Throwable { final CyclicBarrier localBarrier = new CyclicBarrier(2); scheduler.setJobFactory(new JobFactory() { @Override public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException { JobDetail jobDetail = bundle.getJobDetail(); Class<? extends Job> jobClass = jobDetail.getJobClass(); try { return jobClass.getConstructor(CyclicBarrier.class).newInstance(localBarrier); } catch (Exception e) { throw new SchedulerException(e); } } }); // start node1's scheduler first to let it run some jobs, then switch to node2 JobDetail lastRunningJob = null; List<JobExecutionContext> contextList = null; scheduler.start(); localBarrier.await(); contextList = scheduler.getCurrentlyExecutingJobs(); Assert.assertEquals(contextList.size(), 1); lastRunningJob = contextList.get(0).getJobDetail(); localBarrier.await(); scheduler.shutdown(true); SchedulerMetaData metaData = scheduler.getMetaData(); int numJobsExecuted = metaData.getNumberOfJobsExecuted(); int finalCount = lastRunningJob.getJobDataMap().getIntValue(TestJob.JOB_PROP_NAME); Assert.assertThat(numJobsExecuted, Is.is(1)); Assert.assertThat(finalCount, Is.is(2)); } protected boolean isStartingScheduler() { return false; } } @PersistJobDataAfterExecution public static class TestJob implements Job { public static final String JOB_PROP_NAME = "counter"; private final CyclicBarrier jobBarrier; public TestJob(CyclicBarrier jobBarrier) { this.jobBarrier = jobBarrier; } public void execute(JobExecutionContext context) throws JobExecutionException { try { JobDataMap data = context.getJobDetail().getJobDataMap(); int outputCount = data.getIntValue(JOB_PROP_NAME) + 1; data.put(JOB_PROP_NAME, outputCount); jobBarrier.await(); jobBarrier.await(); } catch (Exception e) { throw new JobExecutionException(e); } } } }