quartz job run only once - java

I have created Job. I want to run it every minute
but it run only once.
following is my java class
String exp = "0 0/1 * 1/1 * ? *";
SchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
scheduler.start();
JobDetail job = JobBuilder.newJob(schedulartest.class).build();
Trigger trigger = TriggerBuilder.newTrigger()
.startNow()
.withSchedule(
CronScheduleBuilder.cronSchedule(exp))
.build();
scheduler.scheduleJob(job, trigger);
when i execute it it run only first time.
can someone help to figure out these

This is how you should do it :
CronScheduleBuilder cronSchedule = CronScheduleBuilder.cronSchedule( "* * * * * ?" );
Trigger trigger = TriggerBuilder.newTrigger().withIdentity( "trigger-" + id, group ).withSchedule( cronSchedule ).build();
scheduler.scheduleJob( job, trigger );

Related

How to restrict cron trigger executed a job only once when fired in quartz scheduler

In my quartz scheduler my Main class is executed 5 or 6 times when a cron trigger firedin every 20 seconds.I want to restrict to execute Main class only once when cron trigger fired in every 20 seconds
This is my CronTrigger
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
JobDetail job = JobBuilder.newJob(Main.class).build();
Date startTime = DateBuilder.nextGivenSecondDate(null, 10);
// run every 20 seconds infinite loop
CronTrigger crontrigger = TriggerBuilder.newTrigger().startAt(startTime).withSchedule(CronScheduleBuilder.cronSchedule("0/20 * * * * ?")).build();
scheduler.start();
scheduler.scheduleJob(job, crontrigger);
This is Main Class method
Main.java
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("Trigger Starts..");
}
My actual output is
Trigger 1 - When cron fires first time it will execute 3 or 4 times
Trigger Starts..
Trigger Starts..
Trigger Starts..
Trigger 2 - When cron fires second time it will execute 6 or 7 times
Trigger Starts..
Trigger Starts..
Trigger Starts..
Trigger Starts..
Trigger Starts..
Trigger Starts..
Trigger Starts..
Trigger Starts..
6 or 7 times this Main class is called. I want to restrict this situation
My expected output is
Trigger 1 (first 20 sec)
Trigger Starts..
Trigger 2 (next 20 sec)
Trigger Starts..
It should be executed once
On my system, I tested it and it works perfectly fine. Can you please use the following template and please share it's output and some info about logger if used.
Job:
public void execute(JobExecutionContext context) throws JobExecutionException
{
int count;
if(context.get("count") == null)
context.put("count", count = 1);
else
context.put("count", count = (Integer) context.get("count") + 1);
System.out.println("Hello Quartz!, Count: " + count);
}
This is my CronTrigger:
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
JobDetail job = JobBuilder.newJob(HelloJob.class).build();
// run every 20 seconds infinite loop
CronTrigger crontrigger = TriggerBuilder.newTrigger().withSchedule(
CronScheduleBuilder.cronSchedule("0/20 * * * * ?")).build();
scheduler.start();
scheduler.scheduleJob(job, crontrigger);

What happens if I do not shutdown() quartz scheduler

What would happen if I do not call the shutdown() method on my Quartz scheduler?
I have a job that needs to be run each day at different times the day:
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDetail job = newJob(NotificationCronJob.class).withIdentity("notificationJob1", "notificationGroup1").build();
CronTrigger cronTriggerSunday = newTrigger().withIdentity("notificationTrigger1", "notificationGroup1")
.withSchedule(cronSchedule(Config.SUNDAY_NOTIFY))
.forJob(job)
.build();
CronTrigger cronTriggerMonday = newTrigger().withIdentity("notificationTrigger2", "notificationGroup1")
.withSchedule(cronSchedule(Config.MONDAY_NOTIFY))
.forJob(job)
.build();
CronTrigger cronTriggerTuesday = newTrigger().withIdentity("notificationTrigger3", "notificationGroup1")
.withSchedule(cronSchedule(Config.TUESDAY_NOTIFY))
.forJob(job)
.build();
CronTrigger cronTriggerWednesday = newTrigger().withIdentity("notificationTrigger4", "notificationGroup1")
.withSchedule(cronSchedule(Config.WEDENSDAY_NOTIFY))
.forJob(job)
.build();
CronTrigger cronTriggerThursday = newTrigger().withIdentity("notificationTrigger5", "notificationGroup1")
.withSchedule(cronSchedule(Config.THURSDAY_NOTIFY))
.forJob(job)
.build();
CronTrigger cronTriggerFriday = newTrigger().withIdentity("notificationTrigger6", "notificationGroup1")
.withSchedule(cronSchedule(Config.FRIDAY_NOTIFY))
.forJob(job)
.build();
CronTrigger cronTriggerSaturday = newTrigger().withIdentity("notificationTrigger7", "notificationGroup1")
.withSchedule(cronSchedule(Config.SATURDAY_NOTIFY))
.forJob(job)
.build();
scheduler.scheduleJob(job, cronTriggerSunday);
scheduler.scheduleJob(cronTriggerMonday);
scheduler.rescheduleJob(cronTriggerMonday.getKey(), cronTriggerMonday);
scheduler.scheduleJob(cronTriggerTuesday);
scheduler.scheduleJob(cronTriggerWednesday);
scheduler.scheduleJob(cronTriggerThursday);
scheduler.scheduleJob(cronTriggerFriday);
scheduler.scheduleJob(cronTriggerSaturday);
scheduler.start();
Each Config.DAY is a cron expression fore example 0 0 9 ? * 1 run each sunday at 9am.
Now the problem is if I shutdown the scheduler the job would never be run, so therefore I just start it and just let it run. But I am concerned with if that would result in some memory leak og threading problem of some kind, I cannot figure out if this is a well enough solution. My quartz properties are as follows:
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.MSSQLDelegate
org.quartz.jobStore.dataSource = myDS
org.quartz.dataSource.myDS.driver = com.microsoft.sqlserver.jdbc.SQLServerDriver
org.quartz.dataSource.myDS.URL = jdbc:sqlserver://localhost;databaseName=myDB
org.quartz.dataSource.myDS.user = myUser
org.quartz.dataSource.myDS.password = myPassword
org.quartz.dataSource.myDS.maxConnections = 5
org.quartz.jobStore.tablePrefix = QRTZ_
What I need to achieve in the end is an application that runs a job at the defined times and the scheduling should be mutable without restarting the application.
Quartz scheduler shouldn't call 'shutdown' method while your application is running. If you found any problem such as memory leak, you can issue the problem to Quartz community.
If 'shutdown' is called, Quartz scheduler is never restarted even if you call 'start' method again.
Please refer to the below URL which is Quartz documentation.
http://www.quartz-scheduler.org/documentation/quartz-2.x/cookbook/ShutdownScheduler.html

how to reschedule quartz job dynamically

I am trying to update the quartz job scheduling dynamically:
Initially it is after every 3 minute, but dynamically i want to make it 1 min.
here's my quartz.xml and java file
quartz.xml
<schedule>
<job>
<name>JOBNAME</name>
<group>GroupDummy</group>
<description>This is Job B</description>
<job-class>in.xyz.MyClass.java</job-class>
</job>
<trigger>
<cron>
<name>dummyTriggerNameB</name>
<group>MYTRIGGER_GROUP</group>
<job-name>JOBNAME</job-name>
<job-group>GroupDummy</job-group>
<cron-expression>0 0/3 * * * ?</cron-expression>
</cron>
</trigger>
</schedule>
MyClass.java
public void execute(JobExecutionContext arg0) throws JobExecutionException {
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger("dummyTriggerNameB", "MYTRIGGER_GROUP");
CronExpression cronExpression = new CronExpression("0 0/1 * * * ?");
cronTrigger.setCronExpression(cronExpression);
scheduler.rescheduleJob("dummyTriggerNameB", "MYTRIGGER_GROUP", cronTrigger);
}
I am trying the above java code to change the time from 3 minute to 1 minute dynamically but it is not happening "cronTrigger" is returning null.
Help to solve this problem so that i can reschedule dynamically.

Add scripts dynamically as jobs using property/xml file in Quartz

Scenario : I want to create a scheduler application which should run shell scripts as per the defined schedule. To keep it simple, I want the user to add script name and execution timings in some external file (properties/xml) which will be used by my application. For now, I am planning to run this application as a background process on Linux server. In future may be we'll make it as a web-app.
What I've tried till now:
I came across xmlschedulingdataprocessorplugin for this purpose but it requires user to write jobs as Java code and then add it in XML file.
I found some examples for scheduling which presently isn't working.
Please suggest some helpful quartz API which can help me in fulfilling this purpose.
UPDATE:
public class CronTriggerExample {
public static void main(String[] args) throws Exception {
String[] a = {"script1.sh:0/10 * * * * ?", "script2.sh:0/35 * * * * ?"};
for (String config : a) {
String[] attr = config.split(":");
System.out.println("Iterating for : "+attr[0]);
JobKey jobKey = new JobKey(attr[0], attr[0]);
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity(attr[0], attr[0])
.withSchedule(CronScheduleBuilder.cronSchedule(attr[1]))
.build();
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.getContext().put("val", config);
JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity(jobKey).build();
scheduler.start();
scheduler.scheduleJob(job, trigger);
System.out.println("=======================");
}
}
}
My HelloJob class:
public class HelloJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
String objectFromContext = null;
Date date = new Date();
try {
SchedulerContext schedulerContext = context.getScheduler().getContext();
objectFromContext = (String) schedulerContext.get("val");
} catch (SchedulerException ex) {
ex.printStackTrace();
}
System.out.println("Triggered "+objectFromContext+" at: "+date);
}
}
OUTPUT:
Iterating for : script1.sh
log4j:WARN No appenders could be found for logger (org.quartz.impl.StdSchedulerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
=======================
Iterating for : script2.sh
=======================
Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:21:50 IST 2016
Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:00 IST 2016
Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:00 IST 2016
Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:10 IST 2016
Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:20 IST 2016
Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:30 IST 2016
Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:35 IST 2016
Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:40 IST 2016
What am I missing? I tried to create new Job for each iteration and assign script names as JobExecutionContext
The below tutorial help you to schedule shell script.
http://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/
By using
Runtime.getRuntime().exec("sh shellscript.sh");
You can run shell script.
I would take the following approach :
You create a class JobShellRunner which will implement Job interface from quartz :
public class JobShellRunner implements Job {
#Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
// here you take need information about the shell script you need to run, from the context and run the shell script
}
}
read properties files (i suppose here it will be available information about which shell script to run and it's schedule information). For each information needed you will create it's context and it's trigger:
JobKey jobKey = new JobKey("jobShellRunner", "group1");
// put in the job key need information about shell script (path, etc)
JobDetail jobA = JobBuilder.newJob(JobShellRunner.class)
.withIdentity(jobKey).build();
Then the trigger (note that on the cron expression you should complete with the one that you read from properties file):
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("dummyTriggerName1", "group1")
.withSchedule(
CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
.build();
Then schedule the job
scheduler.scheduleJob(jobA, trigger);
you can do something like as following way,
First of need to go likewise,
create your java application which has one scheduled-job which will read at
some time interval one propery/xml file which will provide an information
for which shell_file needs to execute and at what time.
While your program's scheduled-job read that property/xml file and getting
information as following,
2.1. Shell-Script-File-Name
2.2. Timing at what time that script needs to be execute.
This information which is read by above(step-2), with help of it, this job
will create newer independent-job which is fully responsible for execute
shell script at particular time.(that time will be your job-time which is
read from your propery/xml file). also take care of it to it should be one time only(as per your requirement).
this above step repeatedly does untill whole information read by this job and every time will generate one newer job.
in case after some time user edit/updated/added new line into property/xml file this java program's scheduled job will read only
that newer changes and accordingly does as like above explained.
you can see below image for better understanding purpose,
For scheduling purpose you can set-up spring-quartz API for schedule job.
here, I am going to give you little bit pseudo code,
public class JobA implements Job {
#Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
// continues read property/xml file untill while file not read
// based upon above read info. generate new job(one time only) at runtime which has capability to execute shell script
// shell script can be execute by java program by this ,
// Runtime.getRuntime().exec("sh /full-path/shell_script_name.sh");
}
}
............
public class CronTriggerExample {
public static void main( String[] args ) throws Exception
{
JobKey jobKeyA = new JobKey("jobA", "group1");
JobDetail jobA = JobBuilder.newJob(JobA.class)
.withIdentity(jobKeyA).build();
Trigger trigger1 = TriggerBuilder
.newTrigger()
.withIdentity("dummyTriggerName1", "group1")
.withSchedule(
CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) // you can set here your comfortable job time...
.build();
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(jobA, trigger1);
}
}
So, this is an idea what I believe and represent over here, which is top-most suitable as per your requirement.

Quartz scheduleJob Exceptions

Ok, so here I've got a Quartz(version 2.2.1) job that should instantiate two other jobs, create and add two triggers for each job, and add both jobs to the scheduler, deleting them after a set interval that's passed in through the JobDataMap.
When this job is run by the scheduler, it throws the following exception:
org.quartz.JobPersistenceException: The job (DEFAULT.countdown15, countdownGroup) referenced by the trigger does not exist.
The exception is thrown at line 71:
sched.scheduleJob(countdown15Trigger2);
I couldn't figure out why the job doesn't exist at that point, since it should have been created by the earlier newJob call and added to the scheduler by line 70:
sched.scheduleJob(countdown15, countdown15Trigger1);
So, I temporarily commented out that line and attempted to run the program again, whereupon I got this exception at line 72:
line 72:
sched.scheduleJob(countdown60, countdown60Trigger1);
exception:
org.quartz.SchedulerException: Trigger does not reference given job!
Ok, so now I've got two scheduleJob calls throwing two different exceptions, even though as far as I can tell I'm following the correct syntax. But the first scheduleJob call must be working correctly, because the exceptions are occurring later in the code, so for now I'll comment out all the other scheduleJob calls and see what happens.
And then I get this error at line 70, the first and now only scheduleJob call:
org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'countdownGroup.countdown15', because one already exists with this identification.
I don't really know where to go from here, so here's the complete code for the top level job. Any ideas?
public class ShowClockJob implements Job {
public ShowClockJob() {}
#Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
JobDataMap dm = context.getJobDetail().getJobDataMap();
int min = dm.getInt("min"); //show's runtime in minutes
int ms = min * 60000; //convert the runtime in minutes to millisec
Scheduler sched = context.getScheduler();
JobDetail countdown15 = newJob(CountdownJob15.class)
.withIdentity(jobKey("countdown15", "countdownGroup"))
.build();
JobDetail countdown60 = newJob(CountdownJob60.class)
.withIdentity("countdown60", "countdownGroup")
.build();
Trigger countdown15Trigger1 = newTrigger()
.withIdentity("countdown15Trigger1", "countdownGroup")
.withSchedule(cronSchedule("45 5 * * * ?")
.withMisfireHandlingInstructionDoNothing())
.forJob(jobKey("countdown15", "countdownGroup"))
.build();
Trigger countdown15Trigger2 = newTrigger()
.withIdentity("countdown15Trigger2", "countdownGroup")
.withSchedule(cronSchedule("55 19,32,46 * * * ?")
.withMisfireHandlingInstructionDoNothing())
.forJob(jobKey("countdown15, countdownGroup"))
.build();
Trigger countdown60Trigger1 = newTrigger()
.withIdentity("countdown60Trigger1", "countdownGroup")
.withSchedule(cronSchedule("0 17,29,44 * * * ?")
.withMisfireHandlingInstructionDoNothing())
.forJob(jobKey("countdown60, countdownGroup"))
.build();
Trigger countdown60Trigger2 = newTrigger()
.withIdentity("countdown60Trigger2", "countdownGroup")
.withSchedule(cronSchedule("50 57 * * * ?")
.withMisfireHandlingInstructionDoNothing())
.forJob("countdown60, countdownGroup")
.build();
try {
sched.scheduleJob(countdown15, countdown15Trigger1);
sched.scheduleJob(countdown15Trigger2);
sched.scheduleJob(countdown60, countdown60Trigger1);
sched.scheduleJob(countdown60Trigger2);
Thread.sleep(ms); //sleep for the length of the showtime,
//...then shut down the countdown jobs
sched.deleteJob(jobKey("countdown15","countdownGroup"));
sched.deleteJob(jobKey("countdown60","countdownGroup"));
} catch (SchedulerException | InterruptedException ex) {
Logger.getLogger(ShowClockJob.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Turns out it was a simple syntax error. In all but the first trigger creation blocks, at the forJob method, I left out the middle two parenthesis that seperated the jobKey and jobGroup into two strings.
So this:
forJob("countdown60, countdownGroup");
Should have been this:
forJob("countdown60", "countdownGroup");

Categories

Resources