View source | View content page | Page history | Printable version   
Toolbox
Main Page
Upload file
What links here
Recent changes
Help

PDF Books
Show collection (0 pages)
Collections help

Search

Projects:ProcessScheduler/TechnicalSpecifications

Contents

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:

Process-Scheduler-Class-Diagram.png

*** Image needs to be updated ***

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:

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:

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:

  1. Through the Process Request window
  2. Directly, through the Process' window
  3. In the background, through the Process' window

The following sequence diagram outlines the flow of execution from the time the user requests a process:

Process-Scheduler-Sequence-Diagram.png

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 , - * /
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:

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.

Closed Discussion Items

Retrieved from "http://wiki.openbravo.com/wiki/Projects:ProcessScheduler/TechnicalSpecifications"

This page has been accessed 8,333 times. This page was last modified on 8 June 2012, at 05:29. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.