Oracle® Retail Job Orchestration and Scheduler Implementation Guide Release 16.0.21 E88078-01 |
|
![]() Previous |
![]() Next |
A process flow is a composition of one or more activities. It is written in a DSL script that contains all the activities that make up a process from start to finish.
A process flow encapsulates a sequence of activities. An activity can be synchronous or asynchronous. In JOS, some of these activities may be invocations of batch jobs.
This section includes the following:
DSL (Domain Specific Language)
Process Variables
Process flow definition is specified in a Domain Specific Language (DSL) built on the top of Groovy. Since Groovy is build on the top of Java Virtual Machine (JVM), Groovy can understand Java and Groovy language constructs. So the process flow DSL can understand the DSL, Groovy, and Java language constructs.
A process is a list of activities. The keywords "begin", "end" and "activity" are the main DSL keywords used in process flow definition. These are described in detail below.
The begin activity in the process flow definition appears as the first activity. There should be only one begin activity. This activity is intended to be the one used for any initialization needed for the process flow.
Activity has two parts, name and action. The name attribute is mandatory and should be used to give a unique name for the activity.
Action section is where the executable code should reside. Any Groovy or Java code can be coded in this section.
There can be one or more activities in a process.
The end activity in process flow definition appears as the last activity. There should be only one end activity. This activity is intended to be the one used for any finalization needed for the process flow.
Variables used between activities can be created and stored in the processVariables map. The process engine also uses some of the variables for its own working in the process variable map. These variables are prefixed with "bdi_internal_". These variables must not be modified inside the DSL code.
Here is how you can use the process variable map for your own use.
// Set Variable
processVariables["VariableName"] = "Some Value"
// Use a variable value
def anotherVariable = processVariables["VariableName"]
This section includes the following:
Process Flow DSL Characteristics
DSL Keywords
Process Flow API
Process Flow Variables
The section describes the characteristics of the process flow DSL.
Every process flow must have a name. The process flow name must match the filename that the process flow is saved into.
Process flows are written in DSL and saved as .flo files.
Process flow is made up of two special activities called "begin" and "end" and a group of user-defined activity nodes.
The begin and end activities will always run.
User-defined activity may or may not run based on SKIP or moveTo logic.
Every user-defined activity must have a unique name within a process flow.
The activity names are used to transfer control from one activity to another. Jumping to an activity is possible using the moveTo function.
Every activity has an action block that does the real work. Small amounts of Groovy/Java code can be put inside the action block.
Local variables can be defined within the action block.
Process variables are defined on top and are accessible to all activities within the process.
There are few implicit variables such as $activityName and $name.
Errors can be thrown using the error <some message> function.
Built-in conditional branching, looping, error handling.
Predefined functions for common tasks to reduce boilerplate code.
Built in REST service DSL can call service with just one line.
Services available to start/restart/monitor process flows programmatically.
Can handle chaining of process flows.
Service credential management framework built in.
Hybrid Cloud ready.
Built in activity SKIP functionality.
Built in activity HOLD and RELEASE functionality.
Built in SPLIT and JOIN functionality between process flows.
SPLIT - one to many
JOIN - many to one
The tables below describe the following:
DSL Keywords
Process Flow API
Process Flow Variables
Table 4-1 DSL Keyword Descriptions
DSL Keywords | Description |
---|---|
process |
Identifies the process flow. Only one keyword in a process flow. |
name |
Used for naming processes and activities. |
var |
Used for initializing process variables. |
begin |
Begin activity block is the first activity in the DSL. It is mandatory and can be used for initialization. |
activity |
The executable component of the process flow. A process flow is composed of many activities. |
action |
Action section is where the executable code should reside. Any Groovy or Java code can be coded in this section. |
on "okay" moveTo |
Use these keywords inside an activity to move to another activity. |
on "error" moveTo |
Use these keywords inside an activity to move to error activity. |
Table 4-2 Process Flow API Descriptions
DSL API | Usage | Description |
---|---|---|
startOrRestartJob(def baseUrl, String jobName, String credentials) |
startOrRestartJob(externalVariables["url"],"JobAbc", externalVariables["urlUserAlias"]) |
Method to start or restart a job in Job Admin. This method sends a POST request to a REST end point in Job Admin. |
waitForJobCompletedOrFailed(def targetActivity, def url, String credentials, int waitMinutes=1) |
waitForJobCompletedOrFailed("JobAbcActivity",externalVariables["url"] + "/resources/batch/jobs/JobAbc/" + processVariables["jobExecutionId"], externalVariables["urlUserAlias"]) |
Method to wait for job to be completed or to fail. This method checks the status of the job and waits until status is COMPLETED or FAILED. |
waitForProcessInstancesToReachStatus(def processInstanceList, def targetStatus=PROCESS_COMPLETED, def logicalAndOrOr = LOGICAL_AND, int waitMinutes=1) |
waitForProcessInstancesToReachStatus(["P~1", "Q~1"], PROCESS_COMPLETED, LOGICAL_OR) |
Method to wait for other process instances to reach a status. |
waitForProcessNamesToReachStatus(Map, processNameToNumberOfExecutionsAfterStartMarkerTime, LocalDateTime startMarkerTime, def targetStatus = PROCESS_COMPLETED, def logicalAndOrOr = LOGICAL_AND, def whichExecutionStatus = LAST_EXECUTION_STATUS, int waitMinutes = 1) |
waitForProcessNamesToReachStatus([P:3, Q:3, R:3], now().minusDays(1), PROCESS_COMPLETED, LOGICAL_AND, LAST_EXECUTION_STATUS) |
Method to wait for processes with names to reach a status. |
persistGlobalUserData(String key, String value) |
persistGlobalUserData("key", "value") |
Method to persist data to be shared with other processes. Persists key value pairs in BDI_SYSTEM_OPTIONS table. |
String findGlobalUserData(String key) |
findGlobalUserData("key") |
Gets value from BDI_SYSTEM_OPTIONS table for a given key. |
Map findAllGlobalUserData(String key) |
findAllGlobalUserData() |
Returns a Map with all user data. |
removeGlobalUserData(String key) |
removeGlobalUserData("key") |
Removes data for given key. |
error |
error "report my error" |
Generate an error condition and jump to the end activity. Process will be marked as failed. |
POST |
POST[externalVariables.url]^externalVariables.urlUserAlias |
Method to make a POST call to a url. |
GET |
GET[externalVariables.url]^externalVariables.urlUserAlias |
Method to make a GET call to a URL. |
DELETE |
DELETE[externalVariables.url]^externalVariables.urlUserAlias |
Method to make a DELETE call to a URL. |
log.infolog.debug |
log.debug "Activity Name: $activityName" |
Adds information to log file. |
Table 4-3 Process Flow Variables
Variables | Implicit or Explicit | Usage Examples | Description |
---|---|---|---|
externalVariables |
Implicit |
def myVar = externalVariables['myKey'] |
These are global variables that apply to all process flows. It comes from System Options table. Installation specific key values will be here. |
processVariables |
Implicit |
var([ "myVar1":"prq", "myVar2":"xyz", "myVar3":"mno" ])//get valuedef aVar = processVariables['myVar1']//put new valueprocessVariables['myVar2'] = "abc" |
These are process level variables that can be shared by all activities. Process variables are automatically persisted. Restart of a process recovers the process variables to the right value where it left off in the previous run. These are the most common variables you should use. Process variables must be declared using the var key word. |
Local variables |
Explicit |
action{ def a = "xyz" def i = 7 i++} |
Any variables can be created with the action block and used as local variables. Local variables defined in one activity is not accessible in another activity. |
Global external variables |
Explicit |
persistGlobalUserData("key1", "value1")def xyz = findGlobalUserData("key1")removeGlobalUserData("key1") |
For inter process dynamic variable sharing one can persist new variable to DB. |
activityName |
Implicit |
println "My activity is ${activityName}" |
Current activity name. |
name |
Implicit |
Println "My process name is ${processName}" |
Current process name. |
When the process engine executes the process flow, the before and after snapshots of the activity are recorded in the process schema.
The information is reported through the Process Flow Admin application. Process Flow Admin is a web application that provides a GUI to manage task workflows. This is useful for tracking the process flows as well as troubleshooting. The snapshots also help when restarting a failed process. From the schema, the process engine can recreate the context to execute a restart and can resume execution from the activity that failed in the previous run.
One process may invoke one or more processes asynchronously. All the processes may run at the same time.
In order to identify these sub-processes, they are named accordingly. Once invoked, the main process has no control over the sub-processes. Each of the processes will run in the same way, as they are invoked independently.
The process instrumentation captures the state of the process at the beginning and end of each activity. This information is persisted into the process schema. For each activity there will be two records, one for before the activity and the other for after the activity.
Table 4-4 Process Schema Table Descriptions
Table Name | Description |
---|---|
BDI_PROCESS_DEFINITION |
This table stores all the process flow definitions. It is loaded at deployment time. |
BDI_PROCESS_EXEC_INSTANCE |
This table tracks all the process flow executions. There is a row for each process flow execution. |
BDI_ACTIVITY_EXEC_INSTANCE |
This table tracks all the activity executions. There are two rows for each activity execution. One to store the before context, and one to store after context |
BDI_ACTIVITY_DYNAMIC_CONFIG |
This table stores the user runtime choices like SKIP, HOLD, and so on, at the activity level |
BDI_SYSTEM_OPTIONS |
This table has all the system level information like URLs, credential aliases, and so on. |
When the activities within a process flow fails, the process status is marked as failed. A failed (or stopped) process flow can be restarted. If there are multiple failed processes, only the latest failed instance can be restarted.
Note: The restart is for an instance that has already run and failed. This is different from running a new instance of the process flow. |
When a process flow is restarted, the system knows the activity that failed (or stopped) in the previous run. During the restart, the process engine will skip all the activities prior to the failed activity. It will restore the context for the activity and resume execution at the failed activity.
Process flow execution does not keep the activity history at the restart. It will overwrite the activity records upon restart.
Each activity instance and the process instance maintain the status of execution in the process schema. Following are the possible values for Activities and Process.
At the begin activity, the process is marked as PROCESS_STARTED. If any activity fails, the process is marked as PROCESS_FAILED. After the end action is completed, the process is marked PROCESS_COMPLETED. A complete list of process flow statuses includes:
PROCESS_STARTED
PROCESS_FAILED
PROCESS_COMPLETED
PROCESS_STOPPING
PROCESS_STOPPED
Similar to process statuses, each activity has also a status. The values include:
ACTIVITY_STARTED
ACTIVITY_FAILED
ACTIVITY_COMPLETED
ACTIVITY_WAITING_DUE_TO_HOLD_STARTED
ACTIVITY_WAITING_DUE_TO_HOLD_COMPLETED
ACTIVITY_WAITING_DUE_TO_JOIN_STARTED
ACTIVITY_WAITING_DUE_TO_JOIN_COMPLETED
ACTIVITY_SKIPPED
ACTIVITY_STOPPING
All the runtime statuses are persisted in the process schema at runtime when the DSL is executed.
The following steps show how to implement a JOS Flow.
Download JosProcessFlow<version>ForAll16.x.xApps_eng_ga.zip and unzip the file.
Create a process flow DSL file that stitches the jobs. DSL is Groovy based and Groovy or Java code can be used with in action block. See the following sample of DSL.
Copy the DSL files to jos-process-home/setup-data/dsl/flows-in-scope folder.
Run the deployer script in the jos-process-home/bin folder to deploy the JOS Process flow.
This section includes the following activity features:
Activities in a process flow can be skipped by setting the skip activity flag through the Process Flow Configurations screen or REST endpoint. The skip flag can be set to expire, based on date and time. If the expiration date is not provided, then that activity will be skipped until the skip flag is removed. When an activity is set to skip, the process flow engine skips that activity and runs the next activity in the flow.
/batch/processes/<processName>/activities/<activityName>?skip=true
Activities in a process flow can be paused by setting the hold activity flag through the Process Flow Configurations screen or REST endpoint. The hold flag can be set to expire, based on date and time. If the expiration date is not provided, then that activity will be paused until the hold flag is removed. When an activity is set to hold, the process flow engine waits on that activity until the hold flag is removed or the time has expired.
/batch/processes/<processName>/activities/<activityName>?hold=true
The Process Flow engine can be configured to call a rest service at each activity. This is useful if the process flow is invoked by an external system (typically a workflow system) and the system wants to be informed of the progress of each activity. This callback can be configured declaratively or programmatically as needed.
The external system will have to implement the CallBack Service that will allow it to receive information from the JOS process flow. The external system can call the process flow, passing the context information as process flow parameters. The process flow will pass the information back when it makes the CallBack Service call.
To start a JOS process flow, the user must a REST service call to the URL
(http://<host>:<port>/bdi-process-flow/resources/batch/processes/operator/<processName>).
The call must be a POST call to the URL.
The process flow start call accepts HTTP query parameters. The format of the query parameters are as follows:
http://localhost:7001/bdi-process-flow/resources/batch/processes/<ProcessName>?processParameters=callerId=<value1>,correlationId=<value2>,callBackServiceDataDetail.<name1>=<value3>,callBackServiceDataDetail.<name2>=<value4>
Spaces are not allowed in query parameters and must be separated by commas.
For example:
http://localhost:7001/bdi-process-flow/resources/batch/processes/Abc_Process?processParameters=callerId=123,correlationId=abc,callBackServiceDataDetail.def=xyz,callBackServiceDataDetail.abc=123
The following is the context information that must be passed to the JOS process flow from the calling system.
callerId - CallerId parameter is used to identify the invoker of process flow. In this case it is CAWA.
correlationId
- Correlation ID is the main identifier used by the calling system (CAWA) to tie the process flow Start call to the eventual CallBack Service call.
callBackServiceDataDetail - <name>= These are additional key value pairs that may be required in the future as required by the caller.
All of the above parameters are optional. However, if the context is not passed, the caller may not be able to associate the invocation with the callback.
A method (invokeCallBackService) is available for the Process Flow DSL that will allow the process flow to call an external service. This service has following features:
The method internally invokes a REST call to the provided URL.
The method uses basic authentication for the rest call. The credentials for the method call must be available in the process flow.
The payload sent from process flow to the invoking application (CAWA) follows the contract as shown in the example in the next section. All of the values, other than keyValueEntryVo, are populated by the Process Flow engine. The DSL writer can modify the keyValueEntryVo before the callback to pass any custom values from the DSL to invoking application (CAWA).
The result of the callback REST service (in CAWA) must be a String value.
If the callback service invocation fails for any reason (such as a network issue), the process flow activity fails and the process flow is marked as failed.
Set up the callback URL in process flow system options. To configure a callback URL, you should add system options such as <serviceName>CallBackServiceUrl, for example, processCallBackServiceUrl.
In the Process Flow Admin console, navigate to the Manage Configurations tab and the System Options sub-tab.
Scroll down to Create New System Options and enter System Option Name and System Option Value. The URL must be a valid ReST Service.
Click Save.
Set up the callback URL credential alias in the process flow. To add the callback URL credential alias, you must add credential alias such as <serviceName>CallBackServiceUrlUserAlias, for example, processCallBackServiceUrlUserAlias.
In the Create New System Options section, select the Create Credentials check box.
Enter System Option Name, Username, and Password for the URL provided in the previous step. If the system option name for the URL is processCallBackServiceUrl, then the system option name for the credential must be processCallBackServiceUrlUserAlias.
Click Save.
Note: Credentials created through the UI are available after a server restart; however, after the redeployment of the application, the credentials must be created again. |
Navigate to the Manage Process Flow tab and select process flow, then go to Process Flow Configurations sub-tab.
Select Callback check box for the activities you want callback to be enabled for. Select Callback URL from the drop-down list.
Click Save.
From the Process Flow DSL activity, you can invoke the callback service, as shown in the examples below. The callBackServiceUrl and callBackServiceUrlUserAlias properties must be set up in the System Options inside process flow.
Example 1: Short Form
Add the following line inside the JOS process flow activity.
def retValue =
invokeCallBackService
(externalVariables.callBackServiceUrl, externalVariables.callBackServiceUrlUserAlias)
Example 2: Long Form
In the long form API, the callBackServiceData is an implicit parameter that is automatically defined, and the user can update it with additional data inside an activity if necessary.
Add the following line inside the JOS process flow activity.
//optionally update some data
callBackServiceData.keyValueEntryVo[0].key = "Some Key"
callBackServiceData.keyValueEntryVo[0].value = "Some Value"
def retValue =
invokeCallBackService
(externalVariables.callBackServiceUrl, externalVariables.callBackServiceUrlUserAlias, callBackServiceData)
The JOS process flow will make a POST REST call to the callBackService URL, passing in the following payload. JSON is the default content type.
Table 4-5 Call Back Service Scenarios
Activity Type | Activity Action | Callback Behavior | Activity Status Sent by Callback | Activity Status if Callback Fails |
---|---|---|---|---|
Any |
None |
Callback will be called after action part is complete. |
|
|
Skip |
Callback will be called after action part is complete. |
|
|
|
Hold |
Callback will be called when hold is released and after the action part of the activity runs. |
|
|
|
Special Cases |
||||
startOrRestartJobActivity |
None |
Callback will be called as soon as the job start or restart call is complete. |
|
|
waitForJobCompletedOrFailed |
None |
Callback will be called after the Job status has reached complete or failed. |
|
|
Restart Scenarios |
||||
startOrRestartJobActivity |
None |
Job will be started or restarted only if the Job was not started earlier or job failed. If the activity failed due to callback failure the job will not be started. |
|
|
waitForJobCompletedOrFailed |
None |
Callback will be called after checking the Job status, if it has reached complete or failed, otherwise process will wait for the job to reach complete or failed status. |
|
|
The Process Flow application uses basic authentication to access the system. The user must belong to BdiProcessAdminGroup, BdiProcessOperatorGroup, or BdiProcessMonitorGroup to use the process flow REST services and process flow admin application.
There are two authorization roles designed for the process flow application: the Operator role and the Admin role. The Admin role has permissions to use all the functions provided by the process flow application. The Operator role has limited access compared to Admin, as identified in the table below. The Monitor role has the fewest access permissions.
Since the process flow can be written in Groovy and DSL, it is prone to programming mistakes. Any custom DSL must be properly tested before deploying. The process flow engine can detect syntax errors only at runtime. So it is possible to load an incorrect process flow and fail during runtime.
At the end of an activity, the process engine invokes the next activity, depending on the result of activity execution (the "moveTo" statement). If you have empty activities (possibly because you commented out the existing invocation statements), make sure the activity result is valid.
If any activity fails, the process is marked as failed. So in case of process failure, examine the activity details to find out which activity failed. Once the failed activity is identified, the process variables can be inspected to look for any issues. The next step would be to look at the logs through the Process Flow Monitor application to see the details of the issue. Once the issue is fixed, either a restart or a new run of the process flow can be used, depending on the requirement.
To address this, verify the logs. It could be due to the missing Credentials Access permission, missing system credentials, or a missing system options or DSL parsing error.
Deleting a process flow from jos-process-home does not delete it from the process flow application because the process flow application refers to the database entries. In order to delete a process flow from the JOS Process Flow application, the script DELETE_PROCESS_FLOW.sql(jos-process-home/setup-data/dml/) must be run in the JOS Schema.
The following best practices for Process Flow DSL include:
Use naming conventions for process flows and activities in the process flow so that they are easily identified. It is recommended that the name of the process flow includes "Process" and the name of activities ends with "Activity".
Use the built-in startOrRestartJob method to start/restart a job in Job Admin.
Use the built-in waitForJobCompletedOrFailed method to wait until job is complete or failed.
Access system options through externalVariables.
Use processVariables to share variables between activities.
Use the built-in waitForProcessInstancesToReachStatus to wait for other process instances.
Use the built-in waitForProcessNamesToReachStatus to wait for other processes.
It is recommended to use flo as the extension for the process flow DSL file.
Use the built-in REST DSL to make rest calls.
Organize process flows as hierarchical parent child flows, where the parent manages the child flows.
Avoid using too many waitFor calls, as active threads can get blocked.