Working with Jobs

This section provides examples for working with Quartz jobs.

Creating a New Job Class

Creating a new job class is simple. Just create a class that implements the org.quartz.Job interface. This interface requires that you implement the execute() method, which is called when the Scheduler determines that the job should execute.

Listing 12.4 demonstrates a simple job that checks a mail server for new mail messages for a specific user. When the Scheduler executes this job, the execute() method is called, and the code connects to a mail server and gets any mail messages. This job simply prints who the message is from and the subject of the mail message.

Listing 12.4. A Quartz Job That Checks a Mail Server for Mail Messages

package org.cavaness.quartzbook.chapter12;

import java.security.NoSuchProviderException;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class CheckEmailJob implements Job {

 String mailHost = "some.mail.host";
 String username = "aUsername";
 String password = "aPassword";

 // Default Constructor
 public CheckEmailJob() {
 super();
 }

 public void execute(JobExecutionContext context) throws JobExecutionException {
 checkMail();
 }

 protected void checkMail() {

 // Get session
 Session session = null;

 try {

 // Get system properties
 Properties props = System.getProperties();

 session = Session.getDefaultInstance(props, null);
 // Get the store
 Store store = session.getStore("pop3");
 store.connect(mailHost, username, password);

 // Get folder
 Folder folder = store.getFolder("INBOX");
 folder.open(Folder.READ_ONLY);

 // Get directory
 Message message[] = folder.getMessages();
 int numOfMsgs = message.length;

 if (numOfMsgs > 0) {
 for (int i = 0, n = numOfMsgs; i < n; i++) {
 System.out.println("(" + i + " of " + numOfMsgs + "): "
 + message[i].getFrom()[0] + "	"
 + message[i].getSubject());
 }
 } else {
 System.out.println("No Messages for user");
 }

 // Close connection
 folder.close(false);
 store.close();
 } catch (NoSuchProviderException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 } catch (MessagingException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 }
 public static void main(String[] args) {
 CheckEmailJob job = new CheckEmailJob();
 job.checkMail();
 }
}

Most of Listing 12.4 involves using the JavaMail API to access the mail server. In terms of implementing a new Quartz job class, very little has to be done. Essentially, you implement the job interface and the execute() method, and it's ready to be scheduled. This is shown in the next example.

Hard Coding Vs Passing In Job Parameters

In Listing 12.4, the mail properties such as host, username, and password were hard-coded within the job class itself. This is rarely a good idea. Later in the chapter, we change the job to pass the parameters in the JobDataMap.

 

Scheduling a Quartz Job

As the previous example demonstrated, it's pretty straight-forward to create a Quartz job. Fortunately, configuring a job with the Scheduler isn't much more difficult. Listing 12.5 shows an example of scheduling the CheckEmailJob from the previous listing.

Listing 12.5. Example Showing How to Schedule the CheckEmailJob

package org.cavaness.quartzbook.chapter12;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;

public class Listing_12_5 {
 static Log logger = LogFactory.getLog(Listing_12_5.class);

 public static void main(String[] args) {
 Listing_12_5 example = new Listing_12_5();
 example.runScheduler();
 }

 public void runScheduler() {
 Scheduler scheduler = null;

 try {
 // Get a Scheduler instance from the Factory
 scheduler = StdSchedulerFactory.getDefaultScheduler();

 // Start the scheduler
 scheduler.start();

 // Create a JobDetail for the Job
 JobDetail jobDetail = new JobDetail("CheckEmailJob",
 Scheduler.DEFAULT_GROUP, CheckEmailJob.class);

 // Create a trigger that fires every 1 hour
 Trigger trigger = TriggerUtils.makeHourlyTrigger();

 trigger.setName("emailJobTrigger");

 // Start the trigger firing from now
 // trigger.setStartTime(new Date());

 // Associate the trigger with the job in the scheduler
 scheduler.scheduleJob(jobDetail, trigger);
 } catch (SchedulerException ex) {
 // deal with any exceptions
 logger.error(ex);
 }
 }

}

The code in Listing 12.5 obtains the Scheduler from the StdSchedulerFactory and starts it. It then creates a JobDetail for the CheckEmailJob and creates a trigger for the job to fire every hour, starting immediately.

Firing a Job One Time

The org.quartz.TriggerUtils class is convenient and contains many useful methods. One of the most useful methods is the one that can schedule a fire-once immediate trigger. Listing 12.6 demonstrates how to fire the CheckEmailJob only once.

Listing 12.6. Using a Fire-Once Trigger for the CheckEmailJob

package org.cavaness.quartzbook.chapter12;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;

public class Listing_12_6 {
 static Log logger = LogFactory.getLog(Listing_12_6.class);

 public static void main(String[] args) {
 Listing_12_6 example = new Listing_12_6();
 example.runScheduler();
 }

 public void runScheduler() {
 Scheduler scheduler = null;

 try {
 // Get a Scheduler instance from the Factory
 scheduler = StdSchedulerFactory.getDefaultScheduler();

 // Start the scheduler
 scheduler.start();
 // Create a JobDetail for the Job
 JobDetail jobDetail = new JobDetail("CheckEmailJob",
 Scheduler.DEFAULT_GROUP, CheckEmailJob.class);

 // Create a trigger that fires every 1 hour
 Trigger trigger = TriggerUtils.makeImmediateTrigger(0, 0);
 trigger.setName("emailJobTrigger");

 // Associate the trigger with the job in the scheduler
 scheduler.scheduleJob(jobDetail, trigger);

 } catch (SchedulerException ex) {
 // deal with any exceptions
 logger.error(ex);
 }
 }
}

Listing 12.6 uses the static makeImmediateTrigger() method on the TRiggerUtils clas and passes 0 for the repeatCount and 0 for the repeatInterval so that the trigger fires only once.

Replacing an Existing Scheduled Job

Quartz provides the flexibility to modify jobs that are already scheduled. It supports this by allowing the JobDetail to be replaced with a modified JobDetail. To show an example of this, let's update our CheckEmailJob class from Listing 12.4. The version that was shown in Listing 12.4 hard-coded the mail properties within the job class. It would be better if those properties were passed in so they could be changed at will; let's change the CheckEmailJob to allow for that. Listing 12.7 shows an updated version of that job.

Listing 12.7. An Updated CheckEmailJob That Allows Properties to Be Passed In

package org.cavaness.quartzbook.chapter12;

import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class CheckEmailJob implements Job {
 public static String HOST_KEY = "mailHost" ;
 public static String USERNAME_KEY = "username";
 public static String PASSWORD_KEY = "password";

 String mailHost = " some.mail.host";
 String username = "aUsername";
 String password = "aPassword";

 public CheckEmailJob() {
 super();
 }
 public void execute(JobExecutionContext context) throws JobExecutionException {
 loadMailProperties(context.getJobDetail().getJobDataMap());
 checkMail();
 }

 protected void loadMailProperties(JobDataMap map) {
 if (map.getString(HOST_KEY) != null) {
 mailHost = map.getString(HOST_KEY);
 }

 if (map.getString(USERNAME_KEY) != null) {
 username = map.getString(USERNAME_KEY);
 }

 if (map.getString(PASSWORD_KEY) != null) {
 password = map.getString(PASSWORD_KEY);
 }
 }
 protected void checkMail() {
 // Get session
 Session session = null;

 try {
 // Get system properties
 Properties props = System.getProperties();

 session = Session.getDefaultInstance(props, null);

 // Get the store
 Store store = session.getStore("pop3");
 store.connect(mailHost, username, password);

 // Get folder
 Folder folder = store.getFolder("INBOX");
 folder.open(Folder.READ_ONLY);

 // Get directory
 Message message[] = folder.getMessages();
 int numOfMsgs = message.length;
 if (numOfMsgs > 0) {
 for (int i = 0, n = numOfMsgs; i < n; i++) {
 System.out.println("(" + i + " of " + numOfMsgs + "): "
 + message[i].getFrom()[0] + "	"
 + message[i].getSubject());
 }
 } else {
 System.out.println("No Messages for user");
 }

 // Close connection
 folder.close(false);
 store.close();
 } catch (NoSuchProviderException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 } catch (MessagingException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 }
 public static void main(String[] args) {
 CheckEmailJob job = new CheckEmailJob();
 job.checkMail();
 }
}

The main difference between the CheckEmailJob from Listing 12.7 and the version in 12.4 is the loadMailProperties() method. This method is called when the job is first executed and checks the JobDataMap to see if the mail properties were set within the map. If so, those are used. If not, the defaults within the job class are used.

Listing 12.8 shows how the properties can be set up within the JobDataMap and passed to the job. This listing also shows how you can change the job by replacing the JobDetail with a modified instance.

Listing 12.8. An Example Showing How to Update a Scheduled Job

package org.cavaness.quartzbook.chapter12;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;
 public class Listing_12_8 {
 static Log logger = LogFactory.getLog(Listing_12_8.class);

 public static void main(String[] args) {
 Listing_12_8 example = new Listing_12_8();
 example.runScheduler();
 }

 public void runScheduler() {
 Scheduler scheduler = null;

 try {
 // Get a Scheduler instance from the Factory
 scheduler = StdSchedulerFactory.getDefaultScheduler();

 // Start the scheduler
 scheduler.start();

 // Create a JobDetail for the Job
 JobDetail jobDetail = new JobDetail("CheckEmailJob",
 Scheduler.DEFAULT_GROUP, CheckEmailJob.class);

 // Set the properties used by the job
 jobDetail.getJobDataMap().put(CheckEmailJob.HOST_KEY, "host1");
 jobDetail.getJobDataMap().put(CheckEmailJob.USERNAME_KEY, "username");
 jobDetail.getJobDataMap().put(CheckEmailJob.PASSWORD_KEY, "password");

 // Create a trigger that fires at 11:30pm every day
 Trigger trigger = TriggerUtils.makeDailyTrigger(23, 30);
 trigger.setName("emailJobTrigger");

 // Associate the trigger with the job in the scheduler
 scheduler.scheduleJob(jobDetail, trigger);

 // Update the Job with a different mail host
 jobDetail.getJobDataMap().put(CheckEmailJob.HOST_KEY, "host2");
 scheduler.addJob(jobDetail, true);

 } catch (SchedulerException ex) {
 // deal with any exceptions
 logger.error(ex);
 }
 }
}

The code in Listing 12.8 shows two things. First, it shows how you can pass mail properties to the job class through the JobDataMap. Second, it illustrates how you can use the addJob() method to update the JobDetail of an already scheduled job. The addJob() method takes a Boolean argument that tells the Scheduler whether to replace the scheduled JobDetail with the one being passed in. The job name and group must match the one within the Scheduler for it to be replaced with the new one. Typically, your code would retrieve the existing job, modify the contents of its JobDataMap, and then resave it.

Updating an Existing Trigger

You might also need to update an existing trigger for a job. You can replace a trigger with a different one as long as it's for the same job. You can replace a trigger by using the rescheduleJob() method on the Scheduler:

Trigger newTrigger = // Create a new Trigger

// Replace the old trigger with a new one
 sched.rescheduleJob(jobName, Scheduler.DEFAULT_GROUP, newTrigger);

 

Listing Jobs in the Scheduler

If you were building a GUI for Quartz, you might need to list the jobs registered with the Scheduler. Listing 12.9 presents an approach for doing just that.

Listing 12.9. An Example of Listing the Jobs Within the Scheduler

package org.cavaness.quartzbook.chapter12;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;

public class Listing_12_9 {
 static Log logger = LogFactory.getLog(Listing_12_9.class);

 public static void main(String[] args) {
 Listing_12_9 example = new Listing_12_9();
 example.runScheduler();
 }

 public void runScheduler() {
 Scheduler scheduler = null;

 try {
 // Get a Scheduler instance from the Factory
 scheduler = StdSchedulerFactory.getDefaultScheduler();

 // Start the scheduler
 scheduler.start();

 // Create a JobDetail for the Job
 JobDetail jobDetail = new JobDetail("CheckEmailJob",
 Scheduler.DEFAULT_GROUP, CheckEmailJob.class);

 // Create a trigger that fires at 11:30pm every day
 Trigger trigger = TriggerUtils.makeDailyTrigger(23, 30);
 trigger.setName("emailJobTrigger");

 // Associate the trigger with the job in the scheduler
 scheduler.scheduleJob(jobDetail, trigger);

 String[] jobGroups = scheduler.getJobGroupNames();
 int numOfJobGroups = jobGroups.length;

 for (int i = 0; i < numOfJobGroups; i++) {
 System.out.println("Group: " + jobGroups[i]
 + " contains the following jobs");

 String[] jobsInGroup = scheduler.getJobNames(jobGroups[i]);
 int numOfJobsInGroup = jobsInGroup.length;

 for (int j = 0; j < numOfJobsInGroup; j++) {
 System.out.println(" - " + jobsInGroup[j]);

 }
 }

 } catch (SchedulerException ex) {
 // deal with any exceptions
 logger.error(ex);
 }
 }
}

Listing 12.9 registers a single job, the CheckEmailJob from Listing 12.7, and then demonstrates how to loop through the JobGroups and list the jobs within each group. In a GUI, this list could be presented in a list box or a drop-down list.

Listing Triggers Within the Scheduler

You can also list the triggers in a manner similar to that in Listing 12.9 The code would look very similar, but with triggers instead.

String[] triggerGroups = sched.getTriggerGroupNames();
int numOfTriggerGroups = triggerGroups.length;
 for (i = 0; i < numOfTriggerGroups; i++) {
 System.out.println("Group: "
 + triggerGroups[i]
 + " contains the following triggers");

 String{[] triggersInGroup = sched.getTriggerNames(triggerGroups[i]);
 int numOfTriggersInGroup = triggersInGroup.length;
 for (j = 0; j < numOfTriggersInGroup; j++) {
 System.out.println("- " + triggersInGroup[j]);
 }
 }

If you need to list the triggers of a single job, you can use the gettriggersOfJob() method found on the Scheduler. This method returns a TRigger[] of the triggers associated with the job.


Scheduling in the Enterprise

Getting Started with Quartz

Hello, Quartz

Scheduling Jobs

Cron Triggers and More

JobStores and Persistence

Implementing Quartz Listeners

Using Quartz Plug-Ins

Using Quartz Remotely

Using Quartz with J2EE

Clustering Quartz

Quartz Cookbook

Quartz and Web Applications

Using Quartz with Workflow

Appendix A. Quartz Configuration Reference



Quartz Job Scheduling Framework(c) Building Open Source Enterprise Applications
Quartz Job Scheduling Framework: Building Open Source Enterprise Applications
ISBN: 0131886703
EAN: 2147483647
Year: N/A
Pages: 148

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net