How to set date and time in Quartz Schedular from database - java

I am trying to set date and time from database in Quartz Schedular but is unable to do so. Please help me out.
Here is my code:
public class CroneScheduler {
public CroneScheduler() throws Exception {
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sche = sf.getScheduler();
sche.start();
JobDetail jDetail;
jDetail = new JobDetail("Newsletter", "NJob", MyJob.class);
//"0 0 12 * * ?" Fire at 12pm (noon) every day
//"0/2 * * * * ?" Fire at every 2 seconds every day
CronTrigger crTrigger = new CronTrigger("cronTrigger", "NJob", "0/2 * * * * ?");
sche.scheduleJob(jDetail, crTrigger);
}
}

If the version of quartz is 1.7.2,then you can use below code:
public void resetJob(String expression){
ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
Scheduler scheduler = (Scheduler) applicationContext.getBean("testScheduler");
try {
CronTriggerBean trigger = new CronTriggerBean();
trigger.setCronExpression(expression);
trigger.setName("testJobTrigger");
trigger.setGroup(Scheduler.DEFAULT_GROUP);
trigger.setJobName("testJobDetail");
scheduler.rescheduleJob("testJobTrigger", Scheduler.DEFAULT_GROUP, trigger);
} catch (SchedulerException | ParseException e) {
e.printStackTrace();
}
}
If the version of quartz is newer than 1.7.2,you can use below code:
public void resetJob(String expression){
ApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
Scheduler scheduler = (Scheduler) applicationContext.getBean("testScheduler");
CronTriggerImpl trigger = null;
try {
TriggerKey triggerKeys = TriggerKey.triggerKey("testJobTrigger",Scheduler.DEFAULT_GROUP);
trigger = new CronTriggerImpl();
trigger.setCronExpression(expression);
trigger.setKey(triggerKeys);//keep key the same
scheduler.rescheduleJob(triggerKeys,trigger);
} catch (ParseException | SchedulerException e) {
e.printStackTrace();
}
}

Related

How to configure trigger's expiration date

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

Using DAO classes for data call in Cron Job

Hi this is my Cron Scheduler
public class CronListener implements ServletContextListener {
Scheduler scheduler = null;
#Override
public void contextInitialized(ServletContextEvent servletContext) {
System.out.println("Context Initialized");
try {
// Setup the Job class and the Job group
JobDetail job = newJob(CronJob.class).withIdentity("CronQuartzJob",
"Webapp").build();
// This is what I've tried as well
/*
* JobDataMap jdm = new JobDataMap(); jdm.put("targetDAO",
* targetDAO);
*/
// Create a Trigger that fires every X minutes.
Trigger trigger = newTrigger()
.withIdentity("CronQuartzJob", "Sauver")
.withSchedule(
CronScheduleBuilder.cronSchedule
("0 0/1 * 1/1 * ? *")).build();
// Setup the Job and Trigger with Scheduler & schedule jobs
scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
#Override
public void contextDestroyed(ServletContextEvent servletContext) {
System.out.println("Context Destroyed");
try {
scheduler.shutdown();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
And here's the Cron Job itself
public class CronJob implements org.quartz.Job {
static Logger log = Logger.getLogger(CronJob.class.getName());
#Autowired
TargetDAO targetDAO;
#Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
try {
targetDAO.getAllTargets();
} catch (Exception e1) {
e1.printStackTrace();
}
log.info("webapp-rest cron job started");
try {
Utils.getProcessed();
} catch (Exception e) {
e.printStackTrace();
}
}
What I'm trying to do is getting a DAO class to call some data into it and call a function through it, every few hours.
But when I call data through the DAO, it always returns empty.
What I've found is that I must map the DAO somehow, I've seen in xml-based cron jobs, but I am unable to map it in this one.
This not exactly an answer, but a workaround,
What I did was made a new class
#EnableScheduling
#Component
public class SpringCronJob {
private static Logger log = Logger.getLogger(SpringCronJob.class.getName());
#Autowired
TargetDAO targetDAO;
#Scheduled(fixedRate = 15000)
public void getPostedTargets() {
try {
log.info(targetDAO.getAllTargets());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
It doesn't need anything else, no scheduler, you just need to add it to your component scan
This is what lead me to it
http://howtodoinjava.com/spring/spring-core/4-ways-to-schedule-tasks-in-spring-3-scheduled-example/

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);
}

cron schedule freeze

I'm using Cron to schedule an the upload of a file to the server in specific time given by the adminstrator. i created an interface on java, where the user can choose the time of execution of the upload program, and submit the chosen values, once submitted the following method is executed:
public class Reminder {
String minute;
//static int i=0;
String heur;
String substr=",";
String patterns;
List<String> list = null;
List<String> lines = new ArrayList<>();
Timer timer;
FTPUploadFileDemo up=new FTPUploadFileDemo();
public void start() throws IOException {
/************ Get the chosen values from the administrator saved in a CSV file *********************************************************/
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader("C:/Users/BACKENDPC1/Desktop/timer.csv"));
String line = null;
while ((line = reader.readLine()) != null) {
lines.add(line);
}} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();}
/**********************create cron patterns *********************************************/
patterns="";
for(int i=0; i<lines.size();i++) {
heur=lines.get(i).substring(0, lines.get(i).indexOf(substr));
minute=lines.get(i).substring(lines.get(i).indexOf(substr) + substr.length());
System.out.println("Time selected is: "+heur+","+minute);
patterns=patterns+minute+" "+heur+" * * *|";
}
System.out.println(patterns);
// Creates the scheduler.
Scheduler scheduler = new Scheduler();
// Schedules the task, once every minute.
scheduler.schedule(patterns,new RemindTask());
scheduler.start();
try {
Thread.sleep(1L * 60L * 1000L);
} catch (InterruptedException e) {
System.out.println(e);
}
// Stops the scheduler.
scheduler.stop();
}
class RemindTask extends TimerTask {
public void run() {
up.Uplaod();
}
}
}
the scheduling works and it runs but, every time the user interface i created freeze, i don't get any error and the program keeps running but the i can't use the interface anymore. can any one help me please.
public void start() throws IOException {
..............
try {
Thread.sleep(1L * 60L * 1000L);
} catch (InterruptedException e) {
System.out.println(e);
}
...............
}
Why you pause main thread for 60 secounds? Scheduler run his own tasks in separate thread, so you shouldn't interrupt execution of main thread.
ALSO, try to put breakpoints and debug your program step by step and localize problem
And don't write math operations like this:
1L * 60L * 1000L
will be enough to write:
1L * 60 * 1000
In addition, every time format your code:
In Eclipse: Ctrl + Shift + F
In IntelliJ IDEA: Ctrl + Alt + L

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