- Main: instantiates, and initiates Quartz classes
- JobTask: the actual job definition
- JobTaskListener: a listener class that monitors the execution of the job
package com.javaeenotes; import java.io.Serializable; public class JobContext implements Serializable { private static final long serialVersionUID = 1L; private String state = "Initial state."; public String getState() { synchronized (state) { return state; } } public void setState(String state) { synchronized (state) { this.state = state; } } }The next code is the job definition class, which implements the method called by the Quartz scheduler. It's recommended to wrap the whole body of the method in a try-block in order to catch any exceptions that might occur. Wrap the exception in the checked JobExecutionException before throwing it. The main thread can deal with the exception later.
package com.javaeenotes; import java.util.Date; import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; // Disallow running multiple jobs based on this class at the same time. @DisallowConcurrentExecution public class JobTask implements Job { @Override public void execute(JobExecutionContext executionContext) throws JobExecutionException { // It's a good idea to wrap the entire body in a try-block, in order to // catch every exception thrown. try { // Retrieve the state object. JobContext jobContext = (JobContext) executionContext .getJobDetail().getJobDataMap().get("jobContext"); // Update state. jobContext.setState(new Date().toString()); // This is just a simulation of something going wrong. int number = 0; number = 123 / number; } catch (Exception e) { throw new JobExecutionException(e); } } }The next class is responsible for monitoring the job. It's also responsible for dealing with exceptions thrown by the job.
package com.javaeenotes; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobListener; public class JobTaskListener implements JobListener { public static final String TRIGGER_NAME = "Trigger"; @Override public String getName() { return TRIGGER_NAME; } @Override public void jobToBeExecuted(JobExecutionContext context) { System.out.println("Job is going to be executed: " + context.getJobDetail().getKey().toString()); } @Override public void jobExecutionVetoed(JobExecutionContext context) { System.out.println("Job is vetoed by trigger: " + context.getJobDetail().getKey().toString()); } @Override public void jobWasExecuted( JobExecutionContext context, JobExecutionException jobException) { System.out.println("Exception thrown by: " + context.getJobDetail().getKey().toString() + " Exception: " + jobException.getMessage()); } }Now, we can use these classes to see how it runs. We use the Main-class for this purpose.
package com.javaeenotes; import org.quartz.JobBuilder; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.JobKey; import org.quartz.JobListener; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleScheduleBuilder; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; import org.quartz.impl.matchers.KeyMatcher; public class Main { @SuppressWarnings("unchecked") public void run() { // The state of the job. JobContext jobContext = new JobContext(); // The value or transfer object provided by Quartz that contains the // state of the job. Save it in JobDetail or Trigger. JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put("jobContext", jobContext); // Create an identifier for the job. JobKey jobKey = new JobKey("jobId", "jobGroup"); // Object that contains the job class and transfer object. JobDetail jobDetail = JobBuilder.newJob(JobTask.class) .withIdentity(jobKey).usingJobData(jobDataMap).build(); // Create the trigger that will instantiate and execute the job. // Execute the job with a 5 seconds interval. Trigger trigger = TriggerBuilder .newTrigger() .withIdentity("triggerId") .withSchedule( SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(5).repeatForever()) .build(); // Setup a listener for the job. JobListener jobListener = new JobTaskListener(); // Use the Quartz scheduler to schedule the job. try { SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.scheduleJob(jobDetail, trigger); // Tell scheduler to listen for jobs with a particular key. scheduler.getListenerManager().addJobListener( jobListener, KeyMatcher.keyEquals(jobKey)); // Start the scheduler after 5 seconds. scheduler.startDelayed(5); } catch (SchedulerException e) { e.printStackTrace(); } // Print the job state with a 3 seconds interval. while (true) { try { System.out.println(jobContext.getState()); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { new Main().run(); } }
The first thing we do is to create the state object, and wrap it in the transfer or value object provided by Quartz. The reason we do this, is because Quartz doesn't let us instantiate the job class ourselves.
The next step is to define and instantiate a JobKey object, which acts as the identifier for our job. This is also used together with the listener to tell the scheduler which jobs we want to monitor.
Then we create a JobDetail object, which contains details of the job. A trigger object is also needed to tell the scheduler when we want our job to be run. This provides a nice separation of the job and run schedule. Using multiple triggers we can run the same job at different times.
Next, we instantiate the listener class.
Finally, we retrieve an instance of the Quartz scheduler to schedule the job with the trigger. The listener class is also added, together with a matcher based on the job identifier. This way, the scheduler knows which jobs the listener is listening to. The scheduler is then started with a delay of 5 seconds.
The resulting output, when we run the Main class:Initial state. Initial state. Job is going to be executed: jobGroup.jobId Exception thrown by: jobGroup.jobId Exception: java.lang.ArithmeticException: / by zero Job is going to be executed: jobGroup.jobId Exception thrown by: jobGroup.jobId Exception: java.lang.ArithmeticException: / by zero Thu Sep 08 18:07:03 CEST 2011 Thu Sep 08 18:07:03 CEST 2011 Job is going to be executed: jobGroup.jobId Exception thrown by: jobGroup.jobId Exception: java.lang.ArithmeticException: / by zero
Quartz installation for Maven 2
To add Quartz to a Maven 2 project, just add the following code to your pom.xml file.org.quartz-scheduler quartz 2.0.2
Very detailed description of Quartz.. Its very resourceful information.
ReplyDeleteI query i have in my mind is, where can we add the code related to sending the jobs status as email, is it after the run() method before while loop.
Aso, if i replace the job 123/0 with some other time-taking job. Does the job execute Asynchronously?
ReplyDeleteAny help would be appreciated.
Kiến thức bạn share thật bổ ích, cảm ơn bạn đã share.
ReplyDeleteTìm hiểu website : Giá đá thạch anh
Kiến thức của tác giả thật hữu ích, thank bạn đã chia sẻ.
ReplyDeleteTrang tham khảo : Thạch anh vụn dải bể cá
Thông tin của bạn thật được, bạn đã share.
ReplyDeleteXem thêm tại website: Vòng tay đá thạch anh
Thông tin của tác giả rất hữu ích, thank bạn đã chia sẻ.
ReplyDeleteXem tại website : Tỳ hưu
Nice tutorial.
ReplyDeleteVisit beginnerstutorialexamples.com for more Java Quartz scheduler tutorial for beginners with examples.
http://www.beginnerstutorialexamples.com/java-quartz-scheduler-tutorial-for-beginners-with-examples/
Good tutorial.
ReplyDeleteLearn more Quartz scheduler tutorial with examples on http://tutorialspointexamples.com/.
http://tutorialspointexamples.com/log4j-tutorial-beginners-eclipse/