How to configure trigger's expiration date - java

I have next JobSchedulerService:
#Slf4j
#Service
#RequiredArgsConstructor
public class QuartzServiceImpl implements JobSchedulerService {
private final SchedulerFactoryBean schedulerFactoryBean;
#Override
public void scheduleJob(LocalDateTime date, Class jobClass, boolean repeatUntilManuallyStopped, Map<String, Object> jobDataMap) {
String expirationDate = date.toString();
String name = jobClass.getName() + "_";;
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(name + expirationDate)
.storeDurably().build();
if(jobDataMap != null){
jobDetail.getJobDataMap().putAll(jobDataMap);
}
jobDetail.getJobDataMap().put("expirationDate", expirationDate);
ZonedDateTime zonedDateTime = date.atZone(ZoneId.systemDefault());
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name + expirationDate)
.startAt(Date.from(zonedDateTime.toInstant()))
.endAt(Date.from(zonedDateTime.plusMinutes(2).toInstant()))
.withSchedule(repeatUntilManuallyStopped ?
SimpleScheduleBuilder.repeatMinutelyForever().withMisfireHandlingInstructionFireNow() : SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionFireNow())
.build();
schedule(jobDetail, trigger, false);
}
#Override
public void scheduleJob(LocalDateTime date, int intervalInMinutes, int count, Class jobClass, Map<String, Object> jobDataMap) {
String expirationDate = date.toString();
String name = jobClass.getName() + "_";
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(name + expirationDate)
.storeDurably().build();
jobDetail.getJobDataMap().putAll(jobDataMap);
jobDetail.getJobDataMap().put("expirationDate", expirationDate);
LocalDateTime currentTime = LocalDateTime.now();
LocalDateTime startDateTime = date;
int decrement = count;
while (decrement != 0) {
startDateTime = startDateTime.minusMinutes(intervalInMinutes);
decrement --;
if(currentTime.compareTo(startDateTime) >= 0) {
startDateTime = currentTime;
break;
}
}
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name + expirationDate)
.startAt(Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant()))
.withSchedule(SimpleScheduleBuilder.repeatMinutelyForTotalCount(count - decrement, intervalInMinutes)
.withMisfireHandlingInstructionFireNow())
.build();
schedule(jobDetail, trigger, false);
}
public Date schedule(JobDetail jobDetail, SimpleTrigger trigger, boolean isUnique) {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
try {
boolean alreadyExists = scheduler.checkExists(jobDetail.getKey());
if(isUnique && alreadyExists) {
throw new ApiException(ApiError.RESOURCE_EXISTS);
} else if(!alreadyExists){
Date date = scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
return date;
} else {
return trigger.getStartTime();
}
} catch (ObjectAlreadyExistsException e) {
if(isUnique) {
ExceptionTracker.captureException(e);
log.error("Could not schedule job with key {} and description {}. Job already exists", jobDetail.getKey().getName(), jobDetail.getDescription());
throw new ApiException(ApiError.INTERNAL_SERVER_ERROR);
} else {
return trigger.getStartTime();
}
} catch (Exception e){
ExceptionTracker.captureException(e);
log.error("Could not schedule job with key {} and description {}. Localized message => {}", jobDetail.getKey().getName(), jobDetail.getDescription(), e.getLocalizedMessage());
throw new ApiException(ApiError.INTERNAL_SERVER_ERROR);
}
}
}
Here I am setting time for expiration after 2 minutes
.endAt(Date.from(zonedDateTime.plusMinutes(2).toInstant()))
And I shutdown the application right after it creates job and trigger. But when I startup again it runs expired trigger, even if the time has passed in table qrtz_triggers.end_time.
My properties file for Quartz:
org.quartz.scheduler.instanceName=PostcreditService
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=5
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.tablePrefix=postcredit.qrtz_
org.quartz.jobStore.isClustered=true
org.quartz.plugin.shutdownHook.class=org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownHook.cleanShutdown=TRUE
Configs:
#Configuration
public class QuartzConfig {
#Autowired
private ApplicationContext applicationContext;
#Autowired
private DataSource dataSource;
#Bean
public JobFactory jobFactory() {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
#Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setQuartzProperties(quartzProperties());
schedulerFactory.setWaitForJobsToCompleteOnShutdown(true);
schedulerFactory.setAutoStartup(true);
schedulerFactory.setJobFactory(jobFactory());
schedulerFactory.setDataSource(dataSource);
return schedulerFactory;
}
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
}
Please, help!

You are setting trigger's expire time correctly using TriggerBuilder.endAt()
And I shutdown the application right after it creates job and trigger.
But when I startup again it runs expired trigger, even if the time has
passed in table qrtz_triggers.end_time.
This happens because on restart quartz checks for misfired triggers and try to rerun those based on the configured mirefire instruction which in your case is withMisfireHandlingInstructionFireNow. Now the thing is that this particluar instruction does not consider the trigger's endAt() time and always set a new nextFireTime and rerun it.
For your case, there are other misfire instructions that you may want to consider like withMisfireHandlingInstructionNowWithExistingCount

Related

Repository is null in job scheduling in spring boot with quartz scheduler

When the user calls the api /bet/{id}/start, the Schedule will immediately be created with name = id, group = Exchanges, every 3rd second on the minute it will automatically call the excute function to process, for example here I will call the findById(id) function of the repository to retrieve and process the data, but the result I get is java.lang.NullPointerException: null
BetController.java
#RestController
#RequestMapping("/api")
#Transactional
public class BetController extends AbstractController {
private MainScheduler mainScheduler;
#RequestMapping(value = "/bet/{id}/start", method = RequestMethod.POST)
public String addAndStartScheduleWithBetId(#PathVariable("id") Long id) {
mainScheduler.addAndStartScheduler(""+id);
return "";
}
}
MainScheduler.java
#Service
public class MainScheduler {
private Scheduler scheduler;
public MainScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
public Scheduler addAndStartScheduler(String betId) {
try {
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(betId,"Exchanges").withSchedule(CronScheduleBuilder.cronSchedule("3 * * ? * * *")).build();
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(betId, "Exchanges") .build();
scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
scheduler.scheduleJob(jobDetail, trigger);
System.out.println(jobDetail.getKey() + ","+ trigger.getKey() + " will run at: " + new Date());
} catch(Exception ex) {
System.out.println(ex);
}
return scheduler;
}
public boolean deleteJobDetail(String name) {
boolean flag = false;
try {
flag = scheduler.deleteJob(jobKey(name, "Exchanges"));
} catch (SchedulerException e) {
e.printStackTrace();
}
return flag;
}
}
BetRepository.java
public interface BetRepository extends CrudRepository<Bet, Long> {
Page<Bet> findAll(Pageable pageable);
Optional<Bet> findById(Long id) ;
}
ScheduleJob.java
public class ScheduleJob implements Job{
#Autowired
private BetRepository betRepository;
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// TODO Auto-generated method stub
System.out.println("key+group trigger: " + context.getTrigger().getKey());
Long id = Long.parseLong(context.getJobDetail().getKey().getName());
System.out.println("Bet repositorys: " + betRepository.findById(id));
}
}
13-07-2021 03:33:03.015 [35m[DefaultQuartzScheduler_Worker-3][0;39m
[1;31mERROR[0;39m
org.quartz.core.ErrorLogger.schedulerError - Job (Exchanges.5 threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception.
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.lang.NullPointerException: null
at com.bot.auto.utils.ScheduleJob.execute(ScheduleJob.java:21)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
... 1 common frames omitted
Modify your MainScheduler so that you get the autowired BetRepository and put it in the scheduler context before starting the schedular and get it in the Job.
#Service
public class MainScheduler {
private Scheduler scheduler;
#Autowired
private BetRepository betRepository;
public MainScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
public Scheduler addAndStartScheduler(String betId) {
try {
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(betId,"Exchanges").withSchedule(CronScheduleBuilder.cronSchedule("3 * * ? * * *")).build();
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(betId, "Exchanges") .build();
scheduler = StdSchedulerFactory.getDefaultScheduler();
schduler.getContext().put("betRepo",betRepository);
scheduler.start();
scheduler.scheduleJob(jobDetail, trigger);
System.out.println(jobDetail.getKey() + ","+ trigger.getKey() + " will run at: " + new Date());
} catch(Exception ex) {
System.out.println(ex);
}
return scheduler;
}
< -----other methods as is---->
}
Change your Job class as below
public class ScheduleJob implements Job{
private BetRepository betRepository;
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// TODO Auto-generated method stub
betRepository= context.get("betRepo"); or context.getScheduler().getContext().get("betRepo");
System.out.println("key+group trigger: " + context.getTrigger().getKey());
Long id = Long.parseLong(context.getJobDetail().getKey().getName());
System.out.println("Bet repositorys: " + betRepository.findById(id));
}
}

Quartz Scheduler task suddenly not running

Task has started,but nerver executed ,Anyone know what's problem there?
Now the Problem is every time i run the code it gives me only The output
Here's the final log
2020-11-02 17:03:30.852 DEBUG 9264 --- [nio-8089-exec-7] c.z.t.c.quartz.QuartzScheduleManager : addNewCronJob() called with: jobInfo = [JobInfo(className=class com.zx.tzgl.cronJob.YearPlanJob, identifier=25ddaab4-3e3b-45e9-84a3-77ff7ca4c049, groupName=zx, cornExpr=00 18 17 02 11 ? 2020, params={PLAY_YEAR_SWITCH_PARAMS={"planType":"1","isOpen":"1","enable":"1","annual":"2020至2025","closeTime":1604307810844,"id":"1"}})]
2020-11-02 17:03:30.852 INFO 9264 --- [nio-8089-exec-7] org.quartz.core.QuartzScheduler : Scheduler SchedulerFactory_$_NON_CLUSTERED started.
Here's my using quartz' version
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
Here's the quartz.properties file content
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 100
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
org.quartz.jobStore.misfireThreshold = 5000
#org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = myQuartzDB
org.quartz.dataSource.myQuartzDB.driver:oracle.jdbc.OracleDriver
#org.quartz.dataSource.myQuartzDB.URL:jdbc:oracle:thin:#//xx.xx.xx.xx:xxxx/cdb1
#org.quartz.dataSource.myQuartzDB.user:xxxx
#org.quartz.dataSource.myQuartzDB.password:xxxx
org.quartz.dataSource.myQuartzDB.URL:jdbc:oracle:thin:#//xx.xx.x.xx:xxxx/szorcl
org.quartz.dataSource.myQuartzDB.user:xxxx
org.quartz.dataSource.myQuartzDB.password:xxxx
org.quartz.dataSource.myQuartzDB.maxConnections:10
org.quartz.jobStore.isClustered=false
Here's Configuartion
#Configuration
public class QuartzConfig {
#Resource
private MyJobFactory myJobFactory;
#Bean(name = "SchedulerFactory")
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setQuartzProperties(quartzProperties());
factory.setJobFactory(myJobFactory);
return factory;
}
#Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("config/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
#Bean
public QuartzInitializerListener executorListener() {
return new QuartzInitializerListener();
}
#Bean(name = "quartzScheduler")
public Scheduler scheduler() throws IOException {
return schedulerFactoryBean().getScheduler();
}
}
#Component
public class MyJobFactory extends AdaptableJobFactory {
#Autowired
private AutowireCapableBeanFactory capableBeanFactory;
#Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
Here's the schduler manager
#Component
#Slf4j
public class QuartzScheduleManager implements QuartzScheduleI {
#Resource(name = "quartzScheduler")
private Scheduler scheduler;
#Override #SneakyThrows
public void checkAndAddCornJob(JobInfo jobInfo) {
if (isExistJob(jobInfo)) {
resumeJob(jobInfo);
} else {
addNewCronJob(jobInfo);
}
}
#Override #SneakyThrows
public boolean isExistJob(JobInfo jobInfo) {
return scheduler.checkExists(new JobKey(jobInfo.getIdentifier(), jobInfo.getGroupName()));
}
#Override #SneakyThrows
public boolean isExistJob2(JobInfo jobInfo) {
boolean isExist = false;
JobKey jobKey1 = new JobKey(jobInfo.getIdentifier(), jobInfo.getGroupName());
List<? extends Trigger> triggers1 = scheduler.getTriggersOfJob(jobKey1);
if (triggers1.size() > 0) {
for (Trigger tg : triggers1) {
if ((tg instanceof CronTrigger) || (tg instanceof SimpleTrigger)) {
isExist = true;
}
}
}
return isExist;
}
private void addNewCronJob(JobInfo jobInfo) throws Exception {
scheduler.start();
//build job info
JobDetail jobDetail = JobBuilder.newJob(jobInfo.getClassName()).
withIdentity(jobInfo.getIdentifier(), jobInfo.getGroupName())
.build();
//add params to job
if (ObjectUtil.isNotNull(jobInfo.getParams()) && !jobInfo.getParams().isEmpty()) {
jobInfo.getParams().forEach((key, value) -> jobDetail.getJobDataMap().put(key, value));
}
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getCornExpr());
CronTrigger trigger = TriggerBuilder.newTrigger().
withIdentity(jobInfo.getIdentifier(), jobInfo.getGroupName())
.forJob(jobDetail)
.withSchedule(scheduleBuilder)
.build();
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
throw new CustomException(ResultCode.PARAM_ERROR.getCode(), e.getMessage());
}
}
Here's the job listener
public class YearPlanJob implements Job {
#Override public void execute(JobExecutionContext jobExecutionContext) {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobDataMap jobDataMap;
if (!jobDetail.getJobDataMap().isEmpty()) {
jobDataMap = jobDetail.getJobDataMap();
} else {
jobDataMap = jobExecutionContext.getTrigger().getJobDataMap();
}
}
}
Here's my test code
public String testQuartzTask() {
Date date = DateUtil.parse("2020-11-02 17:18:00", "yyyy-MM-dd HH:mm:ss");
PlanapplyYear planapplyYear = new PlanapplyYear();
planapplyYear.setCloseTime(new Date());
String jsonParams = JSONUtil.toJsonStr(planapplyYear);
JobInfo jobInfo = new JobInfo();
jobInfo.setClassName(YearPlanJob.class);
jobInfo.setIdentifier(UUID.randomUUID().toString());
jobInfo.setGroupName("zx");
jobInfo.setCornExpr(CronDateUtils.getCron(date));
jobInfo.setParams(ImmutableMap.of(PLAN_YEAR_SWITCH, jsonParams));
mQuartzScheduleManager.checkAndAddCornJob(jobInfo);
}

Quartz scheduler missing job

I am adding a job to quartz scheduler. After that I call the attached debug print jobs function. It does not list the job. Is the function call to getCurrentlyExecutingJobs() maybe limited to return max. of 10 jobs?
public void scheduleManagementEmail(ManagementEmailConfig managementEmailConfig, Scheduler scheduler) throws SchedulerException
{
logger.debug("Scheduling Management Email " +
managementEmailConfig.getManagementEmailConfigId());
String jobKey = "SendManagementEmailJob_" +
managementEmailConfig.getManagementEmailConfigId();
Class<? extends Job> jobClass = SendManagementEmailJob.class;
JobDetail job = JobBuilder.newJob(jobClass).withIdentity(new JobKey(jobKey)).build();
Trigger trigger = sendManagementEmailJob.getTriggerWithSchedule(managementEmailConfig);
trigger.getJobDataMap().put("managementEmailConfigId", managementEmailConfig.getManagementEmailConfigId());
if (!scheduler.checkExists(new JobKey(jobKey)))
{
scheduler.scheduleJob(job, trigger);
}
debugPrintJobs();
}
public void debugPrintJobs() {
try {
logger.debug("Quartz Jobs");
Scheduler s_scheduler = this.getJobScheduler();
List<JobExecutionContext> currentJobs = s_scheduler.getCurrentlyExecutingJobs();
for (JobExecutionContext jobCtx : currentJobs) {
JobKey jobKey = jobCtx.getJobDetail().getKey();
JobDetail jobDetail = s_scheduler.getJobDetail(jobKey);
List<? extends Trigger> triggers = s_scheduler.getTriggersOfJob(jobKey);
Date nextFireTime = null;
if (triggers.size() > 0)
{
nextFireTime = triggers.get(0).getNextFireTime();
}
logger.debug("Name= "+ jobKey.getName() + " Group=" + jobKey.getGroup() + " NextFireTime=" + nextFireTime);
}
} catch (Exception e) {
logger.debug("debugPrintJobs:" + e.getMessage());
}
The method getCurrentlyExecutingJobs() will return only the jobs that are running, not every scheduled job.
To get every scheduled job, you should do something like this:
Scheduler scheduler = getScheduler();
try {
// All scheduled jobs
for (String groupName : scheduler.getJobGroupNames()) {
for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
final List<? extends Trigger> triggersOfJob = scheduler.getTriggersOfJob(jobKey);
// Do something with the info you just got
// ...
}
}
} catch (SchedulerException e) {
log.error("Retrieving jobs", e);
}

Start new job with quartz in Java

I would like understand how to a job, start new job after of finished with quartz in java.
My Jobs Bean:
#Bean
public JobDetailFactoryBean jobDownload() {
JobDetailFactoryBean j = new JobDetailFactoryBean();
j.setJobClass(DownloadJob.class);
j.setName("jobDownload");
j.setGroup("group1");
return j;
}
#Bean
public JobDetailFactoryBean jobRegex() {
JobDetailFactoryBean j = new JobDetailFactoryBean();
j.setJobClass(RegexJob.class);
j.setName("jobRegex");
j.setGroup("group1");
return j;
}
My Trigger Bean:
#Bean
public CronTriggerFactoryBean triggerDownload() {
CronTriggerFactoryBean cron = new CronTriggerFactoryBean();
cron.setName("triggerDownload");
cron.setGroup("group1");
cron.setCronExpression("0 15 17 * * ?");
cron.setJobDetail(jobConfiguration.jobDownload().getObject());
return cron;
}
My Scheduler:
#Bean
public SchedulerFactoryBean sched() {
SchedulerFactoryBean sched = new SchedulerFactoryBean();
try {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
sched.setJobFactory(jobFactory);
// Agendando execução das triggers
sched.setTriggers(triggerConfiguration.triggerDownload()
.getObject());
sched.start();
} catch (Exception e) {
e.printStackTrace();
}
return sched;
}
My Job Executer:
#Service
#Transactional
public class DownloadJob implements Job {
#Autowired
private RegexService service;
#Override
public void execute(JobExecutionContext j) throws JobExecutionException {
try {
DownloadService t = new DownloadService();
File file = t
.fazerDownload(
"nameFile",
"urlName");
service.aplicaTreeRegex(3L, file, 789L);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I would like jobDownload to start jobRegex after finish. How to do that?

Trouble running nested jobs in quartz

I'm using Quartz 1.8 to write some code that runs a job on a daily/weekly/monthly basis. When that job runs it should create a nested job. For some reason though, neither the nested JobDetail nor Trigger wind up with entries in the database, nor do they run.
Here's the example I'm working with:
public class QuartzSSCCE {
private static Logger LOG = Logger.getLogger(QuartzSSCCE.class);
private static long counter = 0L;
private static Scheduler scheduler;
public void scheduleOuterJob(){
try{
LOG.info("About to try to schedule OuterJob");
CronTrigger ct = new CronTrigger("OuterJobTrigger" + counter++, "OuterJobGroup", "30 * * ? * *");
ct.setStartTime((new DateTime(new Date())).plusSeconds(3).toDate());
DateTime endTime = new DateTime(new Date());
endTime = endTime.plusMinutes(5);
ct.setEndTime(endTime.toDate());
JobDetail jd = new JobDetail("OuterJobDetail" + counter++, "OuterJobGroup", OuterJob.class);
scheduler.scheduleJob(jd, ct);
} catch (Exception e){
LOG.fatal("something went wrong while scheduling the outer job", e);
}
}
public static class OuterJob implements Job {
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try{
LOG.info("running OuterJob");
//Trigger trigger = TriggerUtils.makeImmediateTrigger("InnerTriggerName" + counter++, 1, 1);
SimpleTrigger simpleTrigger = new SimpleTrigger(
"InnerTriggerName" + counter++,
"InnerTriggerGroup",
(new DateTime(new Date())).plusSeconds(10).toDate(),
(new DateTime(new Date()).plusSeconds(50)).toDate(),
1,
1000
);
JobDetail jd = new JobDetail("InnerJobDetail" + counter++, "InnerJobGroup", InnerJob.class);
scheduler.scheduleJob(jd, simpleTrigger);
} catch (Exception e){
LOG.fatal("something went wrong while scheduling the inner job", e);
}
}
}
public static class InnerJob implements Job {
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
LOG.info("InnerJob is running. The time at the beep is: " + new Date());
}
}
public void setScheduler(Scheduler scheduler) {
QuartzSSCCE.scheduler = scheduler;
}
}
This class obtains an Scheduler instance from a SchedulerFactoryBean. Elsewhere in my code I instantiate an instance of QuartzSSCCE like so:
QuartzSSCCE quartzSSCCE = new QuartzSSCCE();
quartzSSCCE.scheduleOuterJob();
I wind up seeing entries in the log for "About to try to schedule OuterJob" and "running OuterJob" but it appears that the InnerJob never gets run. I've attempted this with both a trigger returned from the call to TriggerUtils.makeImmediateTrigger() as well as a SimpleTrigger.
Why won't my InnerJob run?
First of all, my English is poor!
Quartz use reflection to create job instance, as your code show:
JobDetail jd = new JobDetail("InnerJobDetail" + counter++, "InnerJobGroup", InnerJob.class);
But nested class can't create instance directly by reflection, so the InnerJob is not fired.

Categories