Why doesn't quartz work? - java

I work with Quartz lib and I have simple code like this:
public void run() {
try {
SchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
scheduler.start();
JobDetail job = JobBuilder
.newJob(HelloWorldJob.class)
.withIdentity("tJob")
.build();
Trigger t = TriggerBuilder
.newTrigger()
.withIdentity("tTrigger")
.startNow()
.withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(19, 50).inTimeZone(TimeZone.getDefault()))
.build();
scheduler.scheduleJob(job, t);
} catch (Exception e) {
e.printStackTrace();
}
}
And Job class:
public class HelloWorldJob implements Job {
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("HELLO WORLD");
}
}
19:50 - is a time when i expected to see the result.
But it does not work.
What is wrong with this part of code?
Maybe i forgot something. Please, help me.
P.S. I tried with .inTimeZone(TimeZone.getDefault()) and without it. And i hade same result in both.
Holy moly
Today it's work fine. But i swear, yesterday it didn't work.
Maybe problem in time visualization?
Today i set 11 hour and 52 minutes. And it works fine in 11:52 and write "Hello" to console, but yesterday i have written 19:50 and it did not work.
Should i write in another time system? With A.M/P.M?
Or what the hell?

Related

Java Quartz, allow only one thread per job [duplicate]

I am using a Quartz Job for executing specific tasks.
I am also scheduling its execution in my Main application class and what i am trying to accomplish is not to allow simultaneous instances of this job to be executed.
So the scheduler should only execute the job if its previous instance is finished.
Here is my Job class:
public class MainJob implements Job {
static Logger log = Logger.getLogger(MainJob.class.getName());
#Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
GlobalConfig cfg = new GlobalConfig();
ProcessDicomFiles processDicomFiles = new ProcessDicomFiles();
ProcessPdfReportFiles processPdf = new ProcessPdfReportFiles();
try {
log.info("1. ---- SCHEDULED JOB -- setStudiesReadyToProcess");
processDicomFiles.setStudiesReadyToProcess();
log.info("2. ---- SCHEDULED JOB --- distributeToStudies");
processDicomFiles.distributeToStudies(cfg.getAssocDir());
...
//process any incoming PDF file
log.info("11. ---- SCHEDULED JOB --- processPdfFolder");
processPdf.processPdfFolder();
} catch (Exception ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.ERROR, null, ex);
}
log.info(">>>>>>>>>>> Scheduled Job has ended .... <<<<<<<<<<<<<<<<<<<<");
}
}
So in my application's main class i am starting the scheduler:
...
//start Scheduler
try {
startScheduler();
} catch (SchedulerException ex) {
log.log(Level.INFO, null, ex);
}
...
public void startScheduler () throws SchedulerException {
//Creating scheduler factory and scheduler
factory = new StdSchedulerFactory();
scheduler = factory.getScheduler();
schedulerTimeWindow = config.getSchedulerTimeWindow();
JobDetailImpl jobDetail = new JobDetailImpl();
jobDetail.setName("First Job");
jobDetail.setJobClass(MainJob.class);
SimpleTriggerImpl simpleTrigger = new SimpleTriggerImpl();
simpleTrigger.setStartTime(new Date(System.currentTimeMillis() + 1000));
simpleTrigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
simpleTrigger.setRepeatInterval(schedulerTimeWindow);
simpleTrigger.setName("FirstTrigger");
//Start scheduler
scheduler.start();
scheduler.scheduleJob(jobDetail,simpleTrigger);
}
I would like to prevent scheduler from starting a second MainJob instance if another one is still running ...
Just use the #DisallowConcurrentExecution Annotation on top of the Job class.
See this official example or this tutorial about concurrent job execution.
#DisallowConcurrentExecution can do your job but please consider that it would only prevent your class from being run twice on the same node.
Please see #ReneM comment in Quartz 2.2 multi scheduler and #DisallowConcurrentExecution
You can implement StatefulJob or annotate DisallowConcurrentExecution
Be cereful when execute from Job with #DisallowConcurrentExecution method with #Async
The second thread may conflict with the first

How to Reschedule Quartz trigger?

I am trying to learn quartz. I have main method
public static void main(String[] args) throws SchedulerException {
try {
JobDetail job1 = JobBuilder.newJob(Job1.class).withIdentity("job1", "group1").build();
Trigger trigger1 = TriggerBuilder.newTrigger().withIdentity("cronTrigger1", "group1")
.withSchedule(CronScheduleBuilder.weeklyOnDayAndHourAndMinute(3, 12, 38)).build();
Scheduler scheduler1 = new StdSchedulerFactory().getScheduler();
scheduler1.start();
scheduler1.scheduleJob(job1, trigger1);
scheduler1.shutdown();
}
catch (Exception e) {
e.printStackTrace();
}
Which works fine. It prints to the console on 3rd day of the week at 12:38 pm.
Now, what I want to do is to reschedule the trigger, so that it deletes the previous stored trigger and creates a new trigger with new schedule.
I read a lot of things at a lot of places but I just can't seem to understand clearly what I actually have to do, for ex:
public void execute(JobExecutionContext context) throws JobExecutionException {
Trigger newTigger = what ever you want;
Trigger oldTrigger = context.getTrigger()
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.rescheduleJob(oldTrigger.getKey(), newTrigger);
}
tell the scheduler to remove the old trigger with the given key, and
put the new one in its place*
but I can't understand the approach(I do understand what is happening in the code though). Thanks in advance.

Java Job Scheduling: Is this possible with Quartz, if not what are my alternatives?

I need to schedule some periodic jobs and I have hit a roadblock with Quartz.
For example:
I do not think this is possible with Quartz (with a single expression/job):
Run a job every day between 8:30 and 12:45, with a period of five minutes. E.g. 8:30, 8:35, 8:40, .... 12:40, 12:45.
If it was between 8:00 and 12:00 it would be easy but I could not find a way to schedule it except handling 8:30-9:00 and 12:00-12:45 with separate expressions, which I do not want to.
Am I wrong in assuming that this is non-trivial with Quartz? I have also searched for some alternatives but most seem to have a similar cron syntax and I am not sure they could handle it either.
Is there a finer-grained scheduling library that I can use in this scenario?
This is perfectly possible with Quartz and a single trigger. People often focus on Cron triggers, but Quartz supports other trigger types and these are often more suitable. To implement your scheduling scenario, I recommend that you look into the Quartz DailyTimeIntervalTrigger.
In the screenshot below you can see a DailyTimeIntervalTrigger example with attribute values to cover your use-case.
I'm not certain you can do this, as you've hinted at. It seems possible to create a custom Trigger to do it, but then it becomes quite a bit of work. The other option is to split the dual Triggers by day, not time.
public class TestQuartz {
class ActualJob implements Job {
#Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
}
}
class DailyJob implements Job {
#Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
// Run from now (8:45) every 5 minutes until 12:45 (endDate)
Trigger trigger =
newTrigger()
.startNow()
.endAt(endDate) // 12:45 PM TODAY
.withSchedule(
cronSchedule("0 0/5 * 1/1 * ? *"))
.build();
try {
Scheduler sched = context.getScheduler();
sched.scheduleJob(newJob(ActualJob.class).build(), trigger);
} catch (SchedulerException ex) {
throw new JobExecutionException(ex);
}
}
}
#Test
public void testQuartz() throws SchedulerException {
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
// Run once a day starting at 8:45 AM
Trigger dailyTrigger =
newTrigger().withSchedule(cronSchedule("0 45 8 1/1 * ? *")).build();
JobDetail job = newJob(DailyJob.class).build();
sched.scheduleJob(job, dailyTrigger);
}
}

Run 2 parts through one cron job

I am using quartz with cron to schedule 2 jobs . One runs at 12:00 and the other at 14:00 and it runs perfectly. Here's my code.
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
JobDetail job1 = JobBuilder.newJob(FirstInvoiceGeneration.class)
.withIdentity("FirstInvoiceGenerationJob", "group1").build();
Trigger trigger1 = TriggerBuilder
.newTrigger()
.withIdentity("FirstInvoiceGenerationTrigger", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 12 * * ?")).build();
//Simple invoice generation to check which invoice to be generated today
JobDetail job2 = JobBuilder.newJob(TodayInvoiceGeneration.class)
.withIdentity("TodayInvoiceGenerationJob", "group1").build();
Trigger trigger2 = TriggerBuilder
.newTrigger()
.withIdentity("TodayInvoiceGenerationTrigger", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule(0 0 14 * * ?")).build();
//Schedule it
Scheduler scheduler;
try {
scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job1, trigger1);
scheduler.scheduleJob(job2, trigger2);
} catch (SchedulerException e) {
e.printStackTrace();
}
}}
My two classes for running two jobs are :
public class FirstInvoiceGeneration implements Job {
#Override
public void execute(JobExecutionContext arg0)
throws JobExecutionException {
System.out.println("Listener running.");
}
}
my second class for second job is
public class FirstInvoiceGeneration implements Job {
#Override
public void execute(JobExecutionContext arg0)
throws JobExecutionException {
System.out.println("Listener running.");
}
}
Now this runs perfectly , but what i want to do is to have 1 job that runs these two codes. Now i can use this cron expression --> "0 0 12,14 * * ?"
this will make the job run at 12pm , 2pm (my guess :p ). But i want to have only one class that execute one code when time is 12pm and other when time is 2pm. So can someone tell me how i can do it?
Reference. As you can see you can send data to a job by usingJobData() method to a job e.g. ("WORK","FIRST"),("WORK","SECOND").
In a single job class only check for the WORK key and accordingly do the operations you want to do. JobExecutionContext you can retrieve the job data using context.getJobDetails().getJobDataMap()

Running a method once a week at a particular time

I looked all over the place. I looked through Timers and Quartz and I am still confused.
I have a huge class performing different methods. One of those methods is a synchronized method:
public void onSynch()
{
String environment = validateEnvironment(env2);
if (environment == null) return;
try
{
RAT.synchronize(environment);
onSelectEnv();
}
catch (Exception e)
{
// TODO: tell user, log
}
}
I need to be able to create a timer that triggers this method alone once a week at a particular time, every Friday and 3:00 PM for example.
I cannot create separate classes.
I need to be able to put the scheduler inside of this method, or create another method next to it that would create a scheduler and run that sync method.
I would like to suggest to use QUARTZ or Spring Batch for scheduler job.
Try below Quartz Example.
Reference : CronTrigger Tutorial, Example
YourJob.java
public class YourJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
//here your operation
}
}
MySchedule.java
public class MySchedule {
public void startUp() throws Exception {
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
JobDetail yourJob = JobBuilder.newJob(YourJob.class).withIdentity("job1", "group1").build();
/*Run every 30 seconds on Weekdays (Monday through Friday)*/
Trigger trigger_1 = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0,30 * * ? * MON-FRI"))
.build();
/*Run at 10am on the 1st and 15th days of the month*/
Trigger trigger_2 = TriggerBuilder.newTrigger()
.withIdentity("trigger2", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 10am 1,15 * ?"))
.build();
/*Run at 3:30PM of every friday f month*/
Trigger trigger_3 = TriggerBuilder.newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 18 30 ? * 6"))
.build();
scheduler.start();
scheduler.scheduleJob(yourJob, trigger_1);
scheduler.scheduleJob(yourJob, trigger_2);
scheduler.scheduleJob(yourJob, trigger_3);
}
}

Categories