Projects:ProcessScheduler/TechnicalSpecifications
General Considerations
The purpose of the Process Scheduler project is to allow all processes, procedures and reports to be run in the background of Openbravo ERP, and to facilitate scheduling these processes as recurring, for example, to run a report once every day/week/month etc.
Process Scheduling Framework
Overview
The Process Scheduling Framework is designed to provide a simple, uniform way to schedule processes throughout the Openbravo ERP application, whether those processes be direct, background, or recurring, scheduled tasks. The idea is to provide a means by which Processes can be written in a standard way so that the Scheduling Framework can execute them, regardless of a Process' implementation.
To achieve this, Quartz will be integrated into the Openbravo ERP application to accommodate the scheduling, and a standard API will be defined to allow processes to be requested, scheduled with, and run by, the Quartz scheduling framework.
The new Process Scheduling Framework is as follows:
*** Image needs to be updated ***
- Process Scheduler - Used throughout the application to schedule Process Requests.
- Process Scheduler - The interface all processes and reports implement so they are able to be executed by the Process Scheduling Framework.
- Process Request - An class which captures the process request and the details of the request, including the Process to run, its parameters and context/security information (if required).
- Process Execution Context - A context object which represents the environment and parameter state for each run of a particular process.
- Process Lifecycle Manager - Responsible for updating the system of the lifecycle events of each process request and process execution.
- Trigger - The interface all processes and reports implement so they are able to be executed by the Process Scheduling Framework.
Quartz Integration
Quartz is integrated into Openbravo ERP by adding the quartz jar file to the applications lib folder and adding a listener and a couple of context parameters to the web.xml:
<listener> <listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class> </listener> <listener> <listener-class>org.openbravo.base.ProcessSchedulerInitializerListener</listener-class> </listener> ... <context-param> <param-name>shutdown-on-unload</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>start-scheduler-on-load</param-name> <param-value>true</param-value> </context-param>
The ProcessSchedulerInitializerListener replaces the PeriodicBackgroundContextListener that is used in previous versions of Openbravo ERP. It creates a new new ProcessScheduler, gives it a reference to the Quartz scheduler and then stores the ProcessScheduler in the servlet context so that it can be accessed by Openbravo ERP servlets:
public void contextInitialized(ServletContextEvent event) { ... ProcessScheduler scheduler = new ProcessSchedulerImpl(sched); // sched is a reference to the underlying Quartz Scheduler context.setAttribute(PROCESS_SCHEDULER_KEY, scheduler); StdSchedulerFactory factory = (StdSchedulerFactory) ctx.getAttribute(QuartzInitializerListener.QUARTZ_FACTORY_KEY); Scheduler sched = factory.getScheduler(); ProcessScheduler scheduler = new ProcessSchedulerImpl(sched);
The ProcessScheduler is then used throughout the application to schedule ProcessRequests, taking the request information to create Quartz Jobs and Trigger information so that the Processes can be run as background threads.
*** Note: ProcessSchedulerInitializerListener replaces the PeriodicBackgroundContextListener that is used in previous versions of Openbravo ERP.
Process Scheduler
The ProcessScheduler is the core of the Openbravo ERP Process Scheduling implementation - it is responsible for handling all process requests. The Process Scheduler is simply a proxy to the underlying Quartz scheduler. It handles requests for Process Requests, but simply pulls the underlying Quartz JobDetail objects from the ProcessRequest and schedules the JobDetail with the Quartz Scheduler.
Process
Process is an abstract base class which implements the Quartz Job interface so that it can be scheduled to execute by the underlying Quartz scheduler. The Job interface specifies one method:
public void execute(JobExecutionContext jec) throws JobExecutionException;
The abstract base class org.openbravo.scheduling.Process provides a single default implementation of the Job.execute() method:
public abstract class Process implements Job { ... public void execute(JobExecutionContext context) throws JobExecutionException { try { execute((ProcessExecutionContext) context.get(ProcessExecutionContext.KEY)); } catch (Exception e) { e.printStackTrace(); throw new JobExecutionException(e); } }
This implementation simply pulls the ProcessExecution context object from the JobExecutionContext and makes a direct call to the Process.execute(ProcessExecutionContext) method:
public abstract void execute(ProcessExecutionContext) throws Exception;
Any class that is intended to be scheduled through the Process Scheduler needs to extend this abstract Process base class and implement the abstract execute() method. So when the Quartz scheduler triggers an execution of a Job, the implementing class' Process.execute() method is fired.
A trivial example of an Process implementation might be:
public class DummyProcess extends Process { @Override public void execute(ProcessExecutionContext context) throws Exception { String param = context.get("someParam"); System.out.println("Dummy process processing..." + param); }
Process Request
A ProcessRequest (org.openbravo.scheduling.ProcessRequest) is a wrapper around a direct or background process request and its parameters. It contains three pieces of information that are used by the Process Scheduler:
- id (String) - A unique identifier.
- processClass (Class) - The process class to execute. An implementation of the Process interface
- params (Map) - Java map containing all of the parameters the process requires to run.
For example, creating a new ProcessRequest in the Openbravo ERP can be achieved as follows:
ProcessRequest processRequest = new ProcessRequest(Procedure.class); processRequest.put("pinstanceId", String pinstanceId); processScheduler.schedule(processRequest);
A Process Request can be either executed directly or scheduled through the Process Scheduler. If the process is direct, the Process Scheduler executes the process immediately.
If the request is scheduled, the scheduler pulls the information from the ProcessRequest and creates a new JobDetail object which can be scheduled through the Quartz scheduler:
AD_PROCESS_REQUEST
Column | Data Type | Description |
---|---|---|
AD_PROCESS_REQUEST_ID | VARCHAR(60) | Identifier for Process Request |
AD_PROCESS_ID | VARCHAR(60) | Identifier for Process |
CREATED | DATE | Audit data |
CREATEDBY | NUMBER(10,0) | Audit data |
UPDATED | DATE | Audit data |
UPDATEDBY | NUMBER(10,0) | Audit data |
AD_USER_ID | NUMBER(10,0) | Audit data |
AD_CLIENT_ID | NUMBER(10,0) | Audit data |
AD_ORG_ID | NUMBER(10,0) | Audit data |
ISACTIVE | CHAR(1 BYTE) | Audit data |
STATUS | VARCHAR(20) | The status of the process (SCHEDULED, CANCELLED, COMPLETE) |
CHANNEL | VARCHAR(20) | The channel through which the process was requested (direct, background, webservice) |
SCHEDULED_FIRE_TIME | DATE | The time that the process is due to be executed next. |
PREVIOUS_FIRE_TIME | DATE | The time that the process last fired. |
REFIRE_COUNT | NUMBER(10,0) | The number of times the process request has run. |
PROCESS_TRIGGER_ID | VARCHAR(60) | The Process Trigger identifier (table reference) associated with the Process Request |
AD_PROCESS_REQUEST_PARA - to be defined
Column | Description |
---|---|
AD_PROCESS_REQUEST_PARA_ID VARCHAR(60) | Identifier for Process Request Parameter |
Process Execution Context
A ProcessExecutionContext represents a single run of a given Process Request. Each time a trigger associated to a Process Request fires, a new ProcessExecutionContext object is created, creating a copy of all of the requests' parameters that the Process will need to execute.
The
The ProcessExecutionContext is the single parameter that is supplied to a process when it is executed by the Process scheduler. It is the context by which the Process accesses any of the parameters it needs to run, and save any of its log or result information after it has finished executing. It contains:
- id - The unique identifier for the Process Execution Context
- processRequestId - The unique identifier for the original ProcessRequest object.
- processInstance - A reference of the concrete Process implementation to be executed.
- params - A copy of the ProcessRequest parameters. These will not be modified during process execution - they are a snapshot of what was fed into the ProcessRequest.
- obContext (to be defined) -An instance of ObContext which contains all the security and audit information for the defined Process request.
- result - The result of the process, if one was set by the Process implementation.
- log - A log of the Process' execution.
The ProcessExecutionContext is a key element in the new Openbravo ERP Process scheduling functionality, in that it's used to capture the state of a given Process request and run, which can then be used by the Process Scheduler and any ProcessListener implementations.
Each Process Execution will have it's state saved to the AD_PROCESS_RUN table at various points in its execution lifecycle, for example when it is fired it will be saved in the PROCESSING state, and when it is finished it will be moved to the SUCCESS or ERROR states. The persistence of the Process Execution Context will be handled by the Process Lifecycle Listener.
AD_PROCESS_RUN
Column | Data Type | Description |
---|---|---|
AD_PROCESS_RUN_ID VARCHAR(60) | VARCHAR(60) | Identifier for Process Run |
AD_PROCESS_REQUEST_ID | VARCHAR(60) | Identifier for Process |
CREATED | DATE | Audit data |
CREATEDBY | NUMBER(10,0) | Audit data |
UPDATED | DATE | Audit data |
UPDATEDBY | NUMBER(10,0) | Audit data |
AD_USER_ID | NUMBER(10,0) | Audit data |
AD_CLIENT_ID | NUMBER(10,0) | Audit data |
AD_ORG_ID | NUMBER(10,0) | Audit data |
ISACTIVE | CHAR(1 BYTE) | Audit data |
SCHEDULED_START | TIMESTAMP | The time the process is scheduled to run. |
START_TIME | TIMESTAMP | The time the process run started. |
FINISH_TIME | TIMESTAMP | The time the process run finished. |
RUN_TIME | VARCHAR(20) | The actual run time of the process. |
STATUS | VARCHAR(20) | The status of the process run (PROCESSING, SUCCESS, ERROR, CANCELLED) |
RESULT | The result of the process run. | |
LOG | A log of the execution of the process run. |
AD_PROCESS_RUN_PARA - to be defined
Column | Description |
---|---|
AD_PROCESS_RUN_PARA_ID VARCHAR(60) | Identifier for Process Run Parameter |
Process Lifecycle Listener
The ProcessLifecycleListener is responsible for handling events within the Quartz scheduler, such as when a process is executed, when a process is finished, or when something has gone wrong with an execution of a particular process.
The ProcessLifecycleListener implements Quartz SchedulerListener, JobListener and TriggerListener interfaces. The ProcessLifecycleListener is registered with the Quartz Scheduler at application startup time and listens for events. It is registered with the Quartz scheduler in the ProcessSchedulerInitializerListener's contextInitialized() method:
ProcessLifecycleListener pll = new ProcessLifecycleListener(ps); pll.setName("process-lifecycle-listener"); scheduler.addSchedulerListener(pll); scheduler.addGlobalJobListener(pll); scheduler.addGlobalTriggerListener(pll);
The main events the ProcessLifecycleListener handles are the following:
Lifecycle method | Description | Responsibility |
---|---|---|
jobScheduled | The Quartz Scheduler has received a scheduled job. | Update the AD_PROCESS_REQUEST table with SCHEDULED status and scheduled time. |
triggerFired | A trigger has fired to exececute a job. | Create a new ProcessExecutionContext and save state to AD_PROCESS_RUN. |
triggerMisfired | A trigger has failed to fire. | Update AD_PROCESS_RUN indicating that execution has been missed. |
jobToBeExecuted | A job is about to be executed. | Update AD_PROCESS_RUN to PROCESSING and set start time. |
jobWasExecuted | A job was executed. It may or may not have been successful. | Update AD_PROCESS_RUN to SUCCESS or ERROR and set finish time and run time |
triggerComplete | The trigger fired the job successfully and is complete. | |
triggerFinalized | A trigger has finished all of its fire times. | Update AD_PROCESS_REQUEST to COMPLETE and set run information. |
jobUnscheduled | A job has been unscheduled. | Update AD_PROCESS_REQUEST to CANCELLED. |
Triggers
Users will specify the recurrence of process requests at the time of selecting a particular process through the Process Request window. Recurrence information will be stored in the AD_PROCESS_TRIGGER table.
Trigger creation is managed by a Trigger Generator class (TriggerGen). Given the recurrence information loaded from the AD_PROCESS_TRIGGER table (ProcessTriggerData, the TriggerGen parses the information, creating a Quartz Trigger that will execute the associated process at the time(s) specified.
AD_PROCESS_TRIGGER
Column | Data Type | Description |
---|---|---|
AD_PROCESS_TRIGGER_ID | VARCHAR(60) | Identifier for Process Trigger |
AD_CLIENT_ID | NUMBER(10,0) | Audit data |
AD_ORG_ID | NUMBER(10,0) | Audit data |
ISACTIVE | CHAR(1 BYTE) | Audit data |
CREATED | DATE | Audit data |
CREATEDBY | NUMBER(10,0) | Audit data |
UPDATED | DATE | Audit data |
UPDATEDBY | NUMBER(10,0) | Audit data |
NAME | VARCHAR(60) | Name given to the Process Trigger |
DESCRIPTION | VARCHAR(60) | Description of the Process Trigger (e.g Every 5 minutes, 15th of each month etc.) |
START_TIME | The time the trigger will fire for the first time | |
START_DATE | DATE | The date the trigger will fire for the first time |
REPEATS | CHAR(1 BYTE) | Whether the trigger will fire only once or will repeat |
FREQUENCY | The frequency with which the trigger will fire (minutely, hourly, daily, weekly, monthly) | |
MINUTELY_INTERVAL | NUMBER(10,0) | Interval in minutes between firings (displayed only when minutely selected) |
HOURLY_INTERVAL | NUMBER(10,0) | Interval in hours between firings (displayed only when hourly selected) |
DAILY_INTERVAL | NUMBER(10,0) | Interval in days between firings (displayed only when daily selected) |
WEEKLY_MON | CHAR(1 BYTE) | Whether the trigger will fire on Monday (displayed only when weekly selected) |
WEEKLY_TUE | CHAR(1 BYTE) | Whether the trigger will fire on Tuesday (displayed only when weekly selected) |
WEEKLY_WED | CHAR(1 BYTE) | Whether the trigger will fire on Wednesday (displayed only when weekly selected) |
WEEKLY_THU | CHAR(1 BYTE) | Whether the trigger will fire on Thursday (displayed only when weekly selected) |
WEEKLY_FRI | CHAR(1 BYTE) | Whether the trigger will fire on Friday (displayed only when weekly selected) |
WEEKLY_SAT | CHAR(1 BYTE) | Whether the trigger will fire on Saturday (displayed only when weekly selected) |
WEEKLY_SUN | CHAR(1 BYTE) | Whether the trigger will fire on Sunday (displayed only when weekly selected) |
WEEKLY_INTERVAL | NUMBER(10,0) | Interval in weeks between firings (displayed only when daily selected) |
MONTHLY_OPTION | Type of monthly trigger (specific date of each month, first/second/third/fourth Mon/Tue etc., last day of each month) | |
MONTHLY_DATE | NUMBER(10,0) | The specific date in each month to trigger (only displayed if specific month option is chosen) |
MONTHLY_DAY_OF_WEEK | The nth day of the week in each month to trigger (only displayed if first/second/third/fourth option is chosen) | |
MONTHLY_INTERVAL | NUMBER(10,0) | Type of monthly trigger (specific date of each month, first/second/third/fourth Mon/Tue etc., last day of each month) |
FINISHES | CHAR(1 BYTE) | Whether the trigger will finish or continue running indefinitely (only displayed if repeats is true) |
FINISHES_OPTION | Trigger will finish on a certain date or after n repititions | |
FINISHES_DATE | DATE | The specific date the trigger will finish firing (only displayed if FINISHES_OPTION is specific date) |
FINISHES_NUM | NUMBER(10,0) | Trigger will finish firing after n repetitions (only displayed if FINISHES_OPTION is repetitions) |
Legacy / Existing Process Implementation
Procedures
Currently SQL procedures are executed through the WAD generated ActionButtonData class. Each process has its own processXXXX method (where XXXX represents the process id in the AD_PROCESS_ID table). The contents of each method are identical apart from the line:
String strSql = ""; strSql = strSql + " CALL C_YearPeriods(TO_NUMBER(?))";
The SQL procedure that is called from each ActionButtonData.processXXXX method.
Based on process id (XXXX in processXXXX), the SQL procedure name changes (in this case it is C_YearPeriods). This process id is now supplied as a parameter to the Process.execute() method, and is used to select the procedure name from the database dynamically, thus allowing
The contents of this method are moved to the Process.execute method
Standard Reports
Jasper Reports
Java Processes
Scheduling a Process
Overview
Processes may be scheduled/run through the ProcessScheduler in a number of different ways:
- Through the Process Request window
- Directly, through the Process' window
- In the background, through the Process' window
The following sequence diagram outlines the flow of execution from the time the user requests a process:
Requesting a Process through the Process Request Window
Create a window in Openbravo ERP UI (process to be run, timing and simple recurrence and parameters, security options, life cycle).
Requesting a Process through the Process' Window
Direct: The current method to execute a process, through the Process window, will appear to the user to function unchanged. However processes run directly will be run be executed by the ProcessScheduler, enabling the same logging, alerts, emails notifications and other functionality that all other scheduled processes have.
Background: An additional button, Background Run, will be added to each Process' window to enable the Process to be run as a background thread instead of forcing the user to wait for the result.
Process Monitor
Adding Functionality Through Listeners
NEEDS TO BE UPDATED
To be completed
The ProcessMonitor is implemented using Quartz Listeners. Listeners provide a way to execute custom code when events occur within the Quartz Scheduler, such as a Trigger firing, the execution of a Job, a Job finishing, or a problem occurring within the Scheduler itself.
The Listeners are registered with the Quartz Scheduler when the container starts up, just after the Openbravo ERP ProcessScheduler is initialised:
import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; ... public class HttpBaseServlet extends HttpServlet implements ConnectionProvider { protected ConnectionProvider myPool; protected ProcessMonitor myMonitor; ... public void init (ServletConfig config) { ... SchedulerFactory factory = (StdSchedulerFactory) config.getServletContext().getAttribute(QuartzInitializerListener.QUARTZ_FACTORY_KEY); Scheduler scheduler = factory.getScheduler(); myMonitor = new ProcessMonitor(scheduler);
Initializing the ProcessMonitor creates the global Listeners and registers them with the Quartz Scheduler:
import org.quartz.Scheduler; import org.quartz.SchedulerListener; import org.quartz.TriggerListener; import org.quartz.JobListener; public class ProcessMonitor { private Scheduler scheduler; private SchedulerListener schedulerListener; private TriggerListener triggerListener; private JobListener jobListener; ... pubilc ProcessMonitor(Scheduler scheduler) { // Register Listeners with Quartz schedulerListener = new StandardSchedulerListener(); triggerListener = new StandardTriggerListener(); jobListener = new StandardJobListener(); myScheduler.registerJobListener(jobListener); myScheduler.registerSchedulerListener(schedulerListener); myScheduler.registerTriggerListener(triggerListener); }
When the ProcessMonitor is initialized, Job, Trigger and Scheduler Listeners are registered with the Scheduler reference. The ProcessMonitor's global listeners are responsible for:
Process Monitor Responsibilities:
Field Name | Allowed Values | Allowed Special Characters |
---|---|---|
... | ||
Year (Optional) | empty, 1970-2099 | , - * / |
- Updating the AD_PROCESS_RUN table when events are fired, such as jobs being scheduled, jobs finishing, or when problems occur during the scheduling or execution of Processes.
- Sending alerts to relevant users when Processes succeed or fail.
- Sending email notifications (if requested) to relevant users when Processes succeed or fail.
Field Name | Allowed Values | Allowed Special Characters |
---|---|---|
... | ||
Year (Optional) | empty, 1970-2099 | , - * / |
The ProcessMonitor and its registered listeners are responsible for update
All Monitoring Listeners will receive a ProcessScheduler reference so that rescheduling and cancelling of jobs can be performed by the Listeners. As an example, if a Trigger is misfired (the execution time was missed), the Process can be rescheduled after the StandardTriggerListener receives the triggerMisfired() event.
StandardJobListener
The StandardJobListener is an implementation of a Quartz JobListener, which is designed to be registered with the Quartz Scheduler and notified of Quartz Job execution events, such as Quartz Jobs being scheduled, finishing, or failing.
jobToBeExecuted(): Update the AD_PROCESS_REQUEST table, setting the ProcessRequest's status to 'Processing'. jobWasExecuted(): Update the AD_PROCESS_REQUEST table, setting the ProcessRequest's status to either 'Successful' or 'Failed'. Update necessary fields such as Finished Date/Time, output log, output file. Also insert the Process Result int the AD_PROCESS_RUN table. Also send Alerts if necessary.
StandardSchedulerListener
The StandardSchedulerListener is an implementation of a Quartz SchedulerListener, which is designed to be registered with the Quartz Scheduler and notified of Quartz Scheduler events, such as scheduler errors, Quartz Jobs and the Scheduler being paused and resumed.
schedulerError(): Send an Alert that an error has occurred with the ProcessScheduler. May need to be re-initialised. jobScheduled(): Update the AD_PROCESS_REQUEST table, setting the ProcessRequest's status to 'Scheduled'. jobsPaused(): TODO jobsResumed(): TODO
StandardTriggerListener
The StandardTriggerListener is an implementation of a Quartz TriggerListener, which is designed to be registered with the Quartz Scheduler and be notified of Quartz Trigger events, such as Triggers being fired, Triggers completing, and Trigger misfires.
triggerMisfired(): Send an alert to say that a particular execution of the Process has failed.
The Process Monitor Listeners are designed to act like the Quartz JDBCJobStore, updating the database each time a Process/JobDetail is scheduled/executed/finished or when there are any error events that occur within the Scheduler. This should enable the Process Monitor windows to be auto-generated.
Process Set
Advanced Options
Cancel a Process
OBContext class
The OBContext class will be used for process security, defining which users and roles can execute which processes. It will also help identify which user(s) will receive alerts/notifications of process execution results, such as success/failure and reports. The OBContext class is created from the fields in VariablesSecureApp when a user clicks a process button.
class OBContext { private String user; private String role; private String language; private String client; private String organization; private String channel; // direct, scheduled, web service ... private String accessLevel() { // getters and setters and utility methods ... }
Appendix A - Quartz Trigger Reference
Daily (every n days)
If Daily is specified every n days, the TriggerGen will create an instance of a Quartz SimpleTrigger. A SimpleTrigger uses the following properties:
- Start Time
- End Time
- Repeat Count
- Repeat Interval
So for daily recurrences, the number of days specified in the provided field will simply be multiplied by 24 hrs to give the daily recurrence.
Example 1 - Create a daily recurrence that starts at 12.30am and then runs every single day at that time:
Calendar cal = new java.util.GregorianCalendar(2008, cal.JUNE, 10); cal.set(cal.HOUR, 00); cal.set(cal.MINUTE, 30); cal.set(cal.SECOND, 0); cal.set(cal.MILLISECOND, 0); SimpleTrigger trigger = new SimpleTrigger( "triggerName", // name null, // group cal.getTime(), // start time null, // end time SimpleTrigger.REPEAT_INDEFINITELY, 86400L * 1000L);
Example 2 – Create a daily recurrence that starts at 3.15pm and then runs at that time every 100 days:
// Set up calendar as per example above SimpleTrigger trigger = new SimpleTrigger( "triggerName", null, cal.getTime(), null, SimpleTrigger.REPEAT_INDEFINITELY, 100 * 86400L * 1000L);
Daily (every weekday)
If 'Daily' is specified as every weekday, the TriggerGen will create an instance of a Quartz CronTrigger with the value “MON-FRI” in the day of the week field. The following diagram outlines each of the fields of a Cron Expression:
+------------------- seconds (0-59) | +---------------- minute (0 - 59) | | +------------- hour (0 - 23) | | | +---------- day of month (1 - 31) | | | | +------- month (1 - 12) | | | | | +---- day of week (0 – 7 or SUN-SAT) (Sunday=0 or 7) | | | | | | +- year (optional) | | | | | | | * * * * * * * command to be executed
Example 3 – Create a daily recurrence that starts at 3.15pm and runs at that time every weekday:
String cronExpression = “0 15 15 * * MON-FRI”; CronTrigger trigger = new CronTrigger("triggerName", null, cronExpression);
Weekly
Weekly recurrences will be created using a Quartz CronTrigger in much the same way as the Daily (every weekday) recurrence. The days of the week can be specified individually as well as in a sequence, so for example, if we wanted the process in Example 3 (above) to only run on Mondays, Wednesdays and Fridays, we would change the Cron Expression to:
String cronExpression = “0 15 15 ? * MON,WED,FRI”;
Example 4 – Create a weekly recurrence that starts at 6.30am and runs at that time each Thursday and Saturday, every 1 week:
String cronExpression = “0 30 6 ? * THU,SAT”; CronTrigger trigger = new CronTrigger("triggerName", null, cronExpression);
Monthly (specific day of every n months)
Monthly recurrences will also be created using a Quartz CronTrigger. Specifying intermittent months is achieved much more simply than intermittent weeks, as Quartz CronTriggers allow you to use the '/' special character in the month field, which is used to specify increments (see Quartz Cron Reference at the end of this document).
Example 5 – Create a monthly recurrence that starts at 8.29pm and runs at that time on the 5th day of every 1 month:
String cronExpression = “0 29 20 5 * ?”; CronTrigger trigger = new CronTrigger("triggerName", null, cronExpression);
Example 6 – Create a monthly recurrence that starts at 5.45am and runs at that time on the 17th day of every 5 months:
String cronExpression = “0 45 5 17 */5 ?”; CronTrigger trigger = new CronTrigger("triggerName", null, cronExpression);
Monthly (last day of every n months)
Quartz CronTriggers also allow you to use the 'L' special character in the day-of-month field, which indicates the last day of the month.
Example 7 – Create a monthly recurrence that starts at 5.45pm and runs at that time on the last day of every 3 months:
String cronExpression = “0 45 17 L */3 ?”; CronTrigger trigger = new CronTrigger("triggerName", null, cronExpression);
Monthly (nth day e.g Tuesday of each n months)
Finally, Quartz CronTriggers also allow the creation of jobs on the nth day (for example, the 3rd Wednesday) of each month by using the '#' special character
Example 8 – Create a monthly recurrence that starts at midday and runs at that time on the 4th Thursday of every 1 month:
String cronExpression = “0 0 12 5#4 */5 ?”; CronTrigger trigger = new CronTrigger("triggerName", null, cronExpression);
Friday = 5
Example 9 – Create a monthly recurrence that starts at 11.20pm and runs at that time on the 1st Saturday of every 6 months:
String cronExpression = “0 45 5 7#1 */6 ?”; CronTrigger trigger = new CronTrigger("triggerName", null, cronExpression);
Saturday = 6
Quartz Cron Reference
Field Name | Allowed Values | Allowed Special Characters |
---|---|---|
... | ||
Seconds | 0-59 | , - * / |
Minutes | 0-59 | , - * / |
Hours | 0-23 | , - * / |
Day-of-month | 1-31 | , - * ? / L W |
Month | 1-12 or JAN-DEC | , - * / |
Day-of-week | 1-7 or SUN-SAT | , - * ? / L # |
Year (Optional) | empty, 1970-2099 | , - * / |
Complete Quartz Cron Trigger reference.
Open Discussion Items
AWO: There is still no defined way to dynamically embed the parameters for a selected process in the page, or create a generic pop-up or callout to achieve this.