1. Variable
Each process instance needs and uses data to perform the steps it consists of. In Flowable, this data is called variables, and they are stored in the database. When calling an external service (for example, providing input or storing the result of the service call), variables can be used in expressions (for example, selecting the correct outgoing sequence flow in a private gateway) and in Java service tasks.
Process instances can contain variables (called process variables) or execution (specific pointers point to where the process is activated), and user tasks can contain variables. A process instance can have any number of variables. Each variable is stored in ACT_RU_VARIABLE in a row in a database table.
All startProcessInstanceXXX methods have an optional parameter to provide variables when creating and starting process instances. For example, from RuntimeService:
ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);
Variables can be added during process execution. For example (RuntimeService):
void setVariable(String executionId, String variableName, Object value); void setVariableLocal(String executionId, String variableName, Object value); void setVariables(String executionId, Map<String, ? extends Object> variables); void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);
Note that variables can be set locally for a given execution (remember, the process instance includes the execution tree). This variable is visible only in this execution and will not be higher in the execution tree. This can be useful if data should not be propagated to the process instance level, or if the variable has a new value for a specific path in the process instance (for example, when using a parallel path).
Variables can also be retrieved, as shown below. Note that a similar method exists on TaskService. This means that a task, such as execution, can have local variables that are only active during the task.
Map<String, Object> getVariables(String executionId); Map<String, Object> getVariablesLocal(String executionId); Map<String, Object> getVariables(String executionId, Collection<String> variableNames); Map<String, Object> getVariablesLocal(String executionId, Collection<String> variableNames); Object getVariable(String executionId, String variableName); <T> T getVariable(String executionId, String variableName, Class<T> variableClass);
Variables are commonly used for Java delegates, expressions, execution or task listeners, scripts, and so on. In these structures, the current execution or task object is available and can be used for variable setting and retrieval. The easiest way to do this is to:
execution.getVariables(); execution.getVariables(Collection<String> variableNames); execution.getVariable(String variableName); execution.setVariables(Map<String, object> variables); execution.setVariable(String variableName, Object value);
Note that all of the above also apply to local variants.
For History (and backward compatibility reasons), when any of the above calls are made, all variables behind the scenes will be obtained from the database. This means that if you have 10 variables, but only get one variable through getVariable ("myVariable"), the other 9 variables behind the scenes will be obtained and cached. This is not necessarily bad because subsequent calls do not access the database again. For example, when your process defines three consecutive service tasks (thus a database transaction), it may be better to use one call to obtain all variables in the first service task, and then obtain the variables required in each service task separately. Note that this applies to both getting and setting variables.
Of course, this is not appropriate when you use many variables or just want to strictly control database queries and traffic. Other methods have been introduced to control this more strictly by adding a new method with optional parameters to tell the engine whether to extract and cache all variables:
Map<String, Object> getVariables(Collection<String> variableNames, boolean fetchAllVariables); Object getVariable(String variableName, boolean fetchAllVariables); void setVariable(String variableName, Object value, boolean fetchAllVariables);
When true is used for the parameter fetchAllVariables, the behavior will be as follows: when a variable is obtained or set, all other variables will be obtained and cached.
However, when false is used as a value, a specific query is used and no other variables are extracted or cached. Only the values of the variables discussed here will be cached for subsequent use.
2. Transient variable
Transient variables are variables like regular variables, but they are not persistent. Typically, transient variables are used for advanced use cases. If you have questions, use the regular process variable.
The following applies to transient variables:
- No history is stored for transient variables.
- Like regular variables, transient variables are placed on the highest parent node when set. This means that when variables are set at execution time, transient variables are actually stored in the process instance execution. Like regular variables, if you set a variable on a specific execution or task, there will be local variations of the method.
- Process variables can only be accessed before the next wait state in the process definition. Then they left. Here, the wait state means the point saved to the data store in the process instance. Note that asynchronous activity is also a waiting state in this definition!
- Transient variables can only be set by setTransientVariable (name, value), but transient variables will also be returned when calling getVariable (name) (a getTransientVariable (name) also exists, and only transient variables can be checked). The reason is to make it easy to write expressions, and the existing logic of using variables is suitable for both types.
- A transient variable hides a persistent variable with the same name. This means that if persistent and transient variables are set on the process instance and getVariable ("someVariable") is called, the transient variable value will be returned.
You can set and get transient variables in most places where regular variables are exposed:
- Implementation of DelegateExecution in JavaDelegate
- TaskListener implementation on DelegateExecution and DelegateTask
- In a script task by executing an object
- When starting a process instance through a runtime service
- When the task is completed
- An error occurred while calling the runtimeService.trigger method
These methods follow the naming conventions of conventional process variables:
void setTransientVariable(String variableName, Object variableValue); void setTransientVariableLocal(String variableName, Object variableValue); void setTransientVariables(Map<String, Object> transientVariables); void setTransientVariablesLocal(Map<String, Object> transientVariables); Object getTransientVariable(String variableName); Object getTransientVariableLocal(String variableName); Map<String, Object> getTransientVariables(); Map<String, Object> getTransientVariablesLocal(); void removeTransientVariable(String variableName); void removeTransientVariableLocal(String variableName);
The following BPMN diagram shows a typical example:
Suppose the get data service task calls a remote service (for example, using REST). We also assume that some configuration parameters are required and need to be provided when starting the process instance. another
In addition, these configuration parameters are not important for historical audit purposes, so we pass them as transient variables:
ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder() .processDefinitionKey("someKey") .transientVariable("configParam01", "A") .transientVariable("configParam02", "B") .transientVariable("configParam03", "C") .start();
Note that transient variables are available until the user task arrives and saves to the database. For example, in the additional work user task, they are no longer available. Also note that if the extracted data is asynchronous, they will not be available after this step.
When acquiring data (Simplified), it may be as follows:
public static class FetchDataServiceTask implements JavaDelegate { public void execute(DelegateExecution execution) { String configParam01 = (String) execution.getVariable(configParam01); // ... RestReponse restResponse = executeRestCall(); execution.setTransientVariable("response", restResponse.getBody()); execution.setTransientVariable("status", restResponse.getStatus()); } }
The process data will get the response transient variables, analyze it, and store the relevant data of the actual process variables, which we need in the future.
The condition for leaving the sequence flow of a dedicated gateway does not know if a persistent or transient variable (in this case, a state transient variable) is used:
<conditionExpression xsi:type="tFormalExpression">${status == 200}</conditionExpression>
The above article is from Pangu BPM Research Institute: http://vue.pangubpm.com/
Article translation submission: https://github.com/qiudaoke/flowable-userguide
For more articles, you can focus on WeChat official account: