Finally, we need to show the Quartz job that starts the workflow process. When the Scheduler calls it, the Quartz job looks up the name of the workflow and starts it running. If no workflow name has been configured in the JobDataMap, the job exits.
Listing 14.13 shows the WorkflowJob.
Listing 14.13. The Quartz WorkflowJob Is Designed to Call an OSWorkflowJob
public class WorkflowJob implements Job { static Log logger = LogFactory.getLog(WorkflowJob.class); /** * Called by the scheduler to execute a workflow */ public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap jobDataMap = context.getJobDataMap(); String wfName = jobDataMap.getString("WORKFLOW_NAME"); if (wfName != null && wfName.length() > 0) { try { executeWorkflow(wfName, jobDataMap); } catch (Exception ex) { logger.error(ex); throw new JobExecutionException(ex.getMessage()); } } else { logger.error("No Workflow name in JobDataMap"); } } protected void executeWorkflow(String workflowName, JobDataMap jobDataMap) throws WorkflowException { // Create the inputs for the workflow from JobDataMap Map workflowInputs = new HashMap(); Iterator iter = jobDataMap.keySet().iterator(); while (iter.hasNext()) { String key = (String) iter.next(); Object obj = jobDataMap.get(key); workflowInputs.put(key, obj); } // Create and execute the workflow Workflow workflow = new BasicWorkflow("someuser"); workflow.setConfiguration(new DefaultConfiguration()); long workflowId = workflow.initialize(workflowName, 1, workflowInputs); workflow.doAction(workflowId, 1, workflowInputs); } } |
The workflow is actually started in the executeWorkflow() method in Listing 14.13. A new instance of a workflow object is created. It's initialized with the name of the workflow that was read from the JobDataMap. The initialize() and doAction() methods on the workflow instance take a java.util.Map as the third argument. The values in the Map are passed to each function in the workflow through the TRansientVars parameter. If you look back at Listing 14.11, you can see how the SCAN_DIR is being pulled from the transientVars. This data was originally in the JobDataMap.
In this example, we take the JobDataMap from the Quartz job and pass the values into the workflow. This is one of the ways in which integration between the two frameworks is easy and straight-forward.
Finally, Listing 14.14 shows the Scheduler code that is used to schedule the WorkflowJob and store the workflow name and SCAN_DIR into the JobDataMap.
Listing 14.14. The WorkflowJob Is Scheduled as Normal, but the Workflow Name Must Be Stored in the JobDataMap
public class WorkflowScheduler { static Log logger = LogFactory.getLog(WorkflowScheduler.class); public static void main(String[] args) { try { // Create and start the Scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.start(); JobDetail jobDetail = new JobDetail("WorkflowJob", null, WorkflowJob.class); // Store the scan directory and workflow name JobDataMap dataMap = jobDetail.getJobDataMap(); dataMap.put("SCAN_DIR", "c:\quartz-book\input"); dataMap.put("WORKFLOW_NAME", "data-import"); // Create a simple trigger Trigger trigger = TriggerUtils.makeSecondlyTrigger(30000, -1); trigger.setName("WorkflowTrigger"); trigger.setStartTime(new Date()); // schedule the job scheduler.scheduleJob(jobDetail, trigger); } catch (SchedulerException ex) { logger.error(ex); } } } |
You should see no surprises in Listing 14.14. The only thing of interest is that we store the workflow name in the JobDataMap. As with the job-chaining example earlier in this chapter, if you wanted to use the JobInitializationPlugin, you could easily specify the name of the workflow within the file.
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