BPMN Script Tasks
An executable BPMN diagram can contain Script Tasks. In PROCEED, you can use Blockly or pure JavaScript (JS) to create an executable Script Task. The programming in Blockly is limited to the usage of the predefined blocks which resemble many JavaScript possibilities. The programming in JavaScript is more versatile but — compared to Blockly — for advanced Users.
The code of a script task is executed within a sandboxed JavaScript environment, so that it is not able to influence the PROCEED Engine, the Operation System or other process instances.
The following page describes the available JavaScript possibilities and libraries usable in Script Tasks.
JavaScript and PROCEED Libraries
A Script Task can be defined with pure JavaScript. Currently PROCEED supports the ECMAScript 2020 version. Moreover, there are several library functions that can be used for accessing global data, process variables or to trigger network requests.
Ending Scripts: optional return and Error
Scripts can end without a return statement.
Optionally, it can also end with return.
In this case, you should only return an Object.
Its properties (key and value) will write and update the process variables.
A Script Task can also end by a semantic error, which will be
caught by an attached boundary Error or Escalation event. This is done by
throwing an BpmnError or an BpmnEscalation.
If an error is thrown but not caught within the BPMN process, or if the script itself has an error (e.g. syntax error), the token will end its execution. (This only stops the running token, not the whole process.)
Example
The following example is a BPMN process describing the workflow of an online shop which offers to ship products to their customers: The process starts with a received order, then the order gets processed and finally shipped to a customer.
Using the attached boundary elements Error and Escalation, the process can handle exceptional behavior when processing the order: If there is an escalation triggered because of an unusual high amount of ordered products, the customer will be informed of a late shipment. If there occurs an error while processing, the customer is informed that the order got canceled.

Example Script Code
const amount = variable.get('amount'); // amount of the ordered products
const cost = variable.get('cost'); // cost of the ordered products
if (cost < 50) {
// update the costs
try {
// add shipping costs to total cost
variable.set('cost', cost + 5);
} catch (err) {
log.info('Error occured while processing order: ' + err);
throw new BpmnError('A severe error occured while processing');
}
}
if (amount > 100) {
// execute alternative flow to the attached escalation boundary-event
throw new BpmnEscalation('late shipment', 'The order is too much');
}PROCEED Library: Script API
variable
In a Script Task it is possible to read and modify data of the running Process Instance or in the global Data Store.
This can be done via the variable object and its setter and getter functions.
Data Types and Scopes of Data Objects
Data Objects have at least a name and a value.
Because the value is usually changeable, we also call them sometimes “Variables”.
They can be simple data types like string, number, boolean or more complex data types like object and array.
When creating Data Objects, use the serializable JSON data types: string, number, boolean , object or array. Functions or cyclical objects are automatically converted to undefined.
Data Objects exist in different scopes:
- Local Scope: inside a (Script) Task
- Process Instance Scope: outside the Script Task on the level of the entire process instances
- Global Scope: outside the process instance, read and written into the global data store (currently located inside the MS)
Scopes separate Variables from each other, so that the same Variable names can exist in different scopes at the same time. The Local Scope and the Process Instance Scope automatically transfer some Variables into the other scope:
- At the start of each Script Task, the Process Instance variables are once copied into the Local scope of the Script Task.
- After the Script Task execution ended, the Local variables automatically update/override the Process Instance variables outside of the task.
Although we recommend to usually read and write in the Local scope, there are also methods for accessing the outside scopes directly. But pay attention: writing directly into the outside scope can lead to concurrency problem if other (parallel) tasks also write into these process variables at the same time.
Creation of Data Objects
There are multiple ways of creating Data Objects:
- Recommended - use of the UI during process design: it is recommended to define all Data Objects in the Automation tab of the Property Panel while ceating a process in our BPMN Editor. If the Script Task works with a Data Object from the global Data Store, you have to predefine it inside the Data view in the user interface. (For now, it is not possible to dynamically create new Data Objects in the global Data Store at process runtime — it is only allowed to update existing Data Objects which were defined within the UI.)
- use
variable.set(...)orvariable.setProcess(...)to dynamically create new Data Objects at process runtime. All Data Objects defined withvariable.set(...)are inside the Local scope and will be automatically transferred to the Process Instance scope after the Script Task ended. - use
return <obj>to end a Script Task. The properties (key and value) of the returned<obj>object will write and update the Variables inside the Process Instance scope.
Of course, it is also possible to define JavaScript variables with let, const, var. Attention: These variables are only temporary to the Script Task and will be deleted after its execution! They will not be automatically transferred to the Process Instance scope.
JavaScript variables defined with let, const, var are only temporary and will be deleted when the Script Task ends.
Reading Data Objects
There are different getter functions to read the Variables, like variable.get( "<variable-name>" ) (see table). You just specify a variable-name. Some functions allow to read directly from the different scopes and some functions return more details like some meta data.
Global Data Objects from the global Data Store have a more advanced object structure. For example, there are properties like name, value, id, description, displayName, subParameters.
There are two different functions for reading the global Data Objects: .getGlobal( ... ) just returns the value as a string or integer and .getGlobalFull( ... ) returns the full object with all properties.
Global Data Objects also can have nested child objects which are stored in the property subParameters.
These child Data Objects can have the same name as their parent object, so addressing a global Variable must be done with the full hierachical path separated by a dot ., e.g. variable.getGlobal("vacation.vacation-days").
Moreover, global Data Objects are separated into organizational and user data. The former is data belonging to the whole organization space and the latter is data belonging just to a user.
By default, the functions .getGlobal( ... ) and .getGlobalFull( ... ) search for a Data Object inside the user section of the user that has started the process instance, i.e. the process initiator.
An explicit way to mark the same request is to use the modifier @process-initiator. in front of the variable name, e.g. variable.getGlobal("@process-initiator.vacations.remainingDays").
If you want to request (or update) organizational data, you can either use the functions .getGlobalOrg( ... ) and .getGlobalOrgFull( ... ) or you prepend @organization. before the variable name, e.g. variable.getGlobal("@organization.it.incidents.amount").
| Read-API | Access to the process variables. |
|---|---|
.get( "<var-name>" ) | Returns the value of a variable from the Local scope. |
.getAll() | Returns an object containing all local variables and their values. |
.getWithLogs() | Returns an object containing all local variables, their values and their log (array) about the modification time points. |
.getProcess( "<var-name>" ) | Returns the value of a variable from the Process Instance scope. |
.getAllProcess() | Returns an object containing all process instance variables and their values. |
.getWithLogsProcess() | Returns an object containing all global variables, their values and their log (array) about the modification time points plus the modifier. |
.getGlobal( "<var-name>.<child-var-name>" ) | Returns the value property of a Data Object from the global Data Store. By default, it searches in the user space of the Process Initiator for the variable name. The modifiers @organization. in the front of the variable name can be used to explicitly request data from the organization space. (The modifier @user. can also be used to explicitly mark the searched scope, but this is the same as the default behaviour.) |
.getGlobalFull( "<var-name>.<child-var-name>" ) | Returns the full Data Object from the global Data Store with the properties name, value, id, description, displayName, subParameters. Search scope: see .getGlobal() |
.getGlobalOrg( "<var-name>.<child-var-name>" ) | Returns the value property of a Data Object from the organizational space inside the global Data Store. |
.getGlobalOrgFull( "<var-name>.<child-var-name>" ) | Returns the full Data Object from the organizational space inside the global Data Store. |
Setting and Updating Data Objects
There are different setter functions to write/update the Variables, like variable.set( "<variable-name>", <value> ) (see table). You specify a variable-name and the value. There are functions that allow to write directly to the different scopes.
Global Data Objects can only be updated, i.e. a global Data Object must have been created in the UI of the Management System before you try to write something into it — creating a new one at runtime via Script Tasks is not possible.
Global Data Objects work as described in the “Reading Data Objects” section by addressing a variable with the dot-notation.
Within a Script Task, it is only possible to update the value property and not the other properties of the full object.
| Write-API | Access to the process variables. |
|---|---|
.set( "<var-name>", <var-value> ) | Updates the value of a Variable in the local Script Task scope. |
.setProcess( "<var-name>", <var-value> ) | Updates the value of a Variable directly inside the process instance. |
.setGlobal( "<var-name>.<child-var-name>", <var-value> ) | Updates value of an existing global Data Object directly inside the user space of the Process Initiator in the global Data Store (just value, the other attributes are not are not updateable). The modifiers @organization. and @user. in the front of the variable name can be used to explicitly update a Variable inside the user or organization space. Throws an Error, if the Variable does not yet exist in the global Data Store. Throws an Error, if <var-value> is not a simple datatype (e.g. object and array are not allowed). |
.setGlobalOrg( "<var-name>.<child-var-name>", <var-value> ) | Updates value of an existing global Data Object directly inside the organization space in the global Data Store (just value, the other attributes are not are not updateable).Throws an Error, if the Variable does not yet exist in the global Data Store. Throws an Error, if <var-value> is not a simple datatype (e.g. object and array are not allowed). |
Example Code: Process Instance Data
var1 can be predefined outside the ScriptTask.
log.info("\nget('var1'): " + variable.get('var1'));
log.info("\ngetProcess('var1'): " + variable.getProcess('var1'));
log.info('\ngetAll(): ' + JSON.stringify(variable.getAll(), null, 2));
log.info('\ngetAllProcess(): ' + JSON.stringify(variable.getAllProcess(), null, 2));
log.info('\ngetWithLogs(): ' + JSON.stringify(variable.getWithLogs(), null, 2));
log.info('\ngetWithLogsProcess(): ' + JSON.stringify(variable.getWithLogsProcess(), null, 2));
variable.set('var1', 123);
log.info("\nget('var1'): " + variable.get('var1'));
log.info("\ngetProcess('var1'): " + variable.getProcess('var1'));
log.info('\ngetAll(): ' + JSON.stringify(variable.getAll(), null, 2));
log.info('\ngetAllProcess(): ' + JSON.stringify(variable.getAllProcess(), null, 2));
log.info('\ngetWithLogs(): ' + JSON.stringify(variable.getWithLogs(), null, 2));
log.info('\ngetWithLogsProcess(): ' + JSON.stringify(variable.getWithLogsProcess(), null, 2));
variable.setProcess('var1', 456);
log.info("\nget('var1'): " + variable.get('var1'));
log.info("\ngetProcess('var1'): " + variable.getProcess('var1'));
log.info('\ngetAll(): ' + JSON.stringify(variable.getAll(), null, 2));
log.info('\ngetAllProcess(): ' + JSON.stringify(variable.getAllProcess(), null, 2));
log.info('\ngetWithLogs(): ' + JSON.stringify(variable.getWithLogs(), null, 2));
log.info('\ngetWithLogsProcess(): ' + JSON.stringify(variable.getWithLogsProcess(), null, 2));Example Code: global Data Objects
@organization.it.incidents.amount and @process-initiator.vacations.remainingDays must be predefined in the global Data Store (i.e. im Management System)
log.info("\ngetGlobal('vacations.remainingDays'): " + variable.getGlobal('vacations.remainingDays'));
log.info("\ngetGlobal('@process-initiator.vacations.remainingDays'): " + variable.getGlobal('@process-initiator.vacations.remainingDays')); // the same as before
log.info("\ngetGlobalFull('vacations.remainingDays'): " + JSON.stringify(variable.getGlobalFull('vacations.remainingDays'), null, 2)));
log.info("\ngetGlobalFull('@process-initiator.vacations.remainingDays'): " + JSON.stringify(variable.getGlobalFull('@process-initiator.vacations.remainingDays'), null, 2))); // the same as before
log.info('\ngetGlobalOrg('it.incidents.amount'): ' + variable.getGlobalOrg('it.incidents.amount'));
log.info('\ngetGlobal('@organization.it.incidents.amount'): ' + variable.getGlobal('@organization.it.incidents.amount')); // the same as before
log.info('\ngetGlobalOrgFull('it.incidents.amount'): ' + JSON.stringify(variable.getGlobalOrgFull('it.incidents.amount'), null, 2));
log.info('\ngetGlobalFull('@organization.it.incidents.amount'): ' + JSON.stringify(variable.getGlobalFull('@organization.it.incidents.amount'), null, 2)); // the same as before
variable.setGlobal('vacations.remainingDays', 20);
variable.setGlobalOrg('it.incidents.amount', 123);
log.info("\ngetGlobal('vacations.remainingDays'): " + variable.getGlobal('vacations.remainingDays'));
log.info("\ngetGlobal('@process-initiator.vacations.remainingDays'): " + variable.getGlobal('@process-initiator.vacations.remainingDays')); // the same as before
log.info("\ngetGlobalFull('vacations.remainingDays'): " + JSON.stringify(variable.getGlobalFull('vacations.remainingDays'), null, 2)));
log.info("\ngetGlobalFull('@process-initiator.vacations.remainingDays'): " + JSON.stringify(variable.getGlobalFull('@process-initiator.vacations.remainingDays'), null, 2))); // the same as before
log.info('\ngetGlobalOrg('it.incidents.amount'): ' + variable.getGlobalOrg('it.incidents.amount'));
log.info('\ngetGlobal('@organization.it.incidents.amount'): ' + variable.getGlobal('@organization.it.incidents.amount')); // the same as before
log.info('\ngetGlobalOrgFull('it.incidents.amount'): ' + JSON.stringify(variable.getGlobalOrgFull('it.incidents.amount'), null, 2));
log.info('\ngetGlobalFull('@organization.it.incidents.amount'): ' + JSON.stringify(variable.getGlobalFull('@organization.it.incidents.amount'), null, 2)); // the same as before
variable.setGlobal('@process-initiator.vacations.remainingDays', 10);
variable.setGlobal('@organization.it.incidents.amount', 321);
log.info("\ngetGlobal('vacations.remainingDays'): " + variable.getGlobal('vacations.remainingDays'));
log.info("\ngetGlobal('@process-initiator.vacations.remainingDays'): " + variable.getGlobal('@process-initiator.vacations.remainingDays')); // the same as before
log.info("\ngetGlobalFull('vacations.remainingDays'): " + JSON.stringify(variable.getGlobalFull('vacations.remainingDays'), null, 2)));
log.info("\ngetGlobalFull('@process-initiator.vacations.remainingDays'): " + JSON.stringify(variable.getGlobalFull('@process-initiator.vacations.remainingDays'), null, 2))); // the same as before
log.info('\ngetGlobalOrg('it.incidents.amount'): ' + variable.getGlobalOrg('it.incidents.amount'));
log.info('\ngetGlobal('@organization.it.incidents.amount'): ' + variable.getGlobal('@organization.it.incidents.amount')); // the same as before
log.info('\ngetGlobalOrgFull('it.incidents.amount'): ' + JSON.stringify(variable.getGlobalOrgFull('it.incidents.amount'), null, 2));
log.info('\ngetGlobalFull('@organization.it.incidents.amount'): ' + JSON.stringify(variable.getGlobalFull('@organization.it.incidents.amount'), null, 2)); // the same as beforelog
Logging in the PROCEED Engine can be done via the object log. Depending on the
log level and the Engine configuration, the logged message will maybe shown in
the console.
| API | Write a message to the logging system of the Engine. |
|---|---|
.trace( "<message>" ) | Logging with timestamp in log level trace (deactivated by default) |
.debug( "<message>" ) | Logging with timestamp in log level debug (deactivated by default) |
.info( "<message>" ) | Logging with timestamp in log level info |
.warn( "<message>" ) | Logging with timestamp in log level warn |
.error( "<message>" ) | Logging with timestamp in log level error |
Example Code
log.trace('Hello PROCEED - trace()');
log.debug('Hello PROCEED - debug()');
log.info('Hello PROCEED - info()');
log.warn('Hello PROCEED - warn()');
log.error('Hello PROCEED - error()');console
Logging can also done via the object console.
Using this way, the message will be redirected to the logging system of the engine and is essentially nearly the same as the logging functions.
console just supports a few other functions:
| API | Write a message to the logging system of the Engine. |
|---|---|
.log( "<message>" ) | Logging without timestamp. |
.trace( "<message>" ) | Logging with timestamp in log level trace (deactivated by default) |
.debug( "<message>" ) | Logging with timestamp in log level debug (deactivated by default) |
.info( "<message>" ) | Logging with timestamp in log level info |
.warn( "<message>" ) | Logging with timestamp in log level warn |
.error( "<message>" ) | Logging with timestamp in log level error |
.time( "<label>" ) | Starts a timer containing label parameter |
.timeEnd( "<label>" ) | Ends a timer with given label parameter and displays the result in console |
Example Code
console.time('L1');
console.log('Hello PROCEED - log()');
console.trace('Hello PROCEED - trace()');
console.debug('Hello PROCEED - debug()');
console.info('Hello PROCEED - info()');
console.warn('Hello PROCEED - warn()');
console.error('Hello PROCEED - error()');
console.timeEnd('L1');wait( <ms> )
A timeout function which pauses/postpones the script execution.
It is synchronous and blocks the execution until the timeout is passed.
Hint: the popular setTimeout() is not available in a Script Task.
If the entire process is paused from the Management System, all script code is also paused until the process is resumed.
If a pause occurs during a wait(), the system stores the original expiration time of wait().
If the process resumes before this original expiration time, the script waits for the remaining time before continuing with the next instructions.
If the original expiration time has passed after the process resumes, it immediately continues with the next instructions after wait().
| API | |
|---|---|
wait(<milliseconds: number>) | milliseconds for pausing the the Script Task execution |
Example Code
// log with time:
log.info("Before wait()");
wait(10000); // 10s
log.info("After wait()");waitAsync( <ms> ): Promise
The use of waitAsync( <ms> ): Promise is only suitable for advanced users.
It makes code execution asynchronous.
This allows you to achieve multiple semi-parallel code executions.
Like wait() but asynchronous. So, it immediately continues with the next code instructions and does not block the execution.
In this sense, it is similar to the usual setTimeout() but instead of callbacks, it returns a Promise.
Therefore, you can use await or then().
Pausing behavior is the same as for wait().
| API | |
|---|---|
waitAsync(<milliseconds: number>): Promise | milliseconds for pausing the the Script Task execution. Returns a Promise. |
Example Code
waitAsync(10000).then( () => console.info("Finished waiting 10s") );setInterval( <clb>, <ms> ) and clearInterval( <id> )
An interval function which repeatedly calls a callback function (clb) after a timeout (ms).
It is similar to the conventional setInterval() of the Node.js and the Web API.
Hint: the interval timer starts counting after the last interval execution has ended.
The setInterval() function returns an id that is used to stop the interval with clearInterval( <id> ).
A Script Task can only end when all started intervals have finished.
setInterval() is synchronous, i.e. if multiple intervals have been started, one interval execution
blocks other the code execution of other intervals.
If you need to run parallel code executions, you currently have to use multiple Script Tasks connected by a parallel Gateway.
| API | |
|---|---|
setInterval(<clb: function>, <milliseconds: number>): <id: number> | the clb function is repeatly called after the given interval timeout milliseconds ended. Return the id of the interval timer. |
clearInterval( <id: number> ) | stops the interval timer. |
Example Code
let id;
let counter;
let f = function (intervalId, startValue) {
counter = counter ?? startValue ?? 0;
counter++;
log.info('Interval-Id: ' + intervalId + ' Counter: ' + counter);
if (counter > 5) {
log.info('Cancel Interval-Id: ' + intervalId);
clearInterval(intervalId);
}
};
/*
Calling setInterval() with a callback function and timeout.
You can directly have function f as the first parameter.
In this case, we put f into another arrow function, because
id1 is used as the first parameter of f().
*/
id = setInterval(() => f(id, 2), 1000);HTTP Network Requests and Server
networkRequest: sychronous functions
Inside of a Script Task it is possible to send HTTP(S) requests to a given URL.
The prefered way of using networkRequest is with its synchronous methods, i.e. the functions wait until an answer is is received.
Since this are network requests, the completion of the methods sometimes need a while until the response is received.
If the entire process is paused from the Management System, all script code is also paused until the process is resumed. If a pause occurs during a networkRequest.X(), the system stores the response and returns it when the process is resumed.
| API | |
|---|---|
.get( "<url>", [<{options}>]): { response, body } | Sends a GET-Request to a URL |
.post( "<url>", <{body}>, ["<content-type>"], [<{options}>]): { response, body } | Sends a POST-Request to a URL with a body (Object or String) |
.put( "<url>", <{body}>, ["<content-type>"], [<{options}>]): { response, body } | Sends PUT-Request to URL with a body (Object or String) |
.delete( "<url>", [<{options}>]): { response, body } | Sends a DELETE-Request to a URL |
.head( "<url>", [<{options}>]): { response, body } | Sends a HEAD-Request to a URL |
"<url>" is a required parameter defining the endpoint of the network request.
It has the format: <protocol>://[<user>:<password>@]<address>:[<port>]/[<path>]?[<query>]
<protocol>: required, needs to behttporhttps.[<user>:<password>@]: optional, used for Basic HTTP authentification (Base64 encoding intoAuthorization:header)<address>is required and needs to be a DNS domain name or an IP address.[<port>]and[<path>]and[<query>]are optional.- Example:
"https://user:pass@app.example.com:8000/path/to/resource?compressed=true&limit=10"
The ["<content-type>"] is an optional string parameter. Set it to the correct Mime
type
of the transmitted data. It defaults to "text/plain" if body is a string, and
to "application/json" if body is a JS object (because it will automatically be
transformed to JSON before sending).
The [<{options}>] object is optional.
For unsecured HTTP requests, there are two usable properties:
headers: {}: An object of strings containing additional request headers.setHost: true|false: Specifies whether or not to automatically add theHostheader. Defaults totrue.
In case of a secure HTTPS connection, the options object has some additional attributes from https.request.
The network functions only return if the response has a HTTP 2xx status code. The methods return an object that contains two properties: { response, body }
response: is an object that contains meta information about the response. It includes the following properties:.rawHeaders,.rawTrailers,.httpVersionMajor,.httpVersionMinor,httpVersion,.method,.statusCode,.statusMessage,.url,.complete,.aborted,.upgradebody: Body of the response
The functions throw an Error if:
- if the response has a non-2xx statusCode:
{ response, body }will be returned inside theErrorobject - if any error is encountered during the request (e.g. DNS resolution, TCP level errors, or actual HTTP parse errors)
That’s why try-catch must be used around network requests.
Example Code
try {
let { response, body } = networkRequest.put(
'https://localhost:8080/path/to/resource?compressed=true&limit=10',
{
api: '2.0',
data: 'Test data',
id: 1,
},
undefined,
{
headers: {
'X-PROCEED-Example-Header': '33029',
},
rejectUnauthorized: false,
},
);
log.info(JSON.stringify(response, null, 2));
log.info(JSON.stringify(body, null, 2));
} catch (e) {
log.error('-----------PROBLEM------------');
log.error(JSON.stringify(e, null, 2));
}networkRequest: asychronous functions
The use of the asynchronous networkRequest.X() functions is only suitable for advanced users.
It makes code execution asynchronous.
This allows you to achieve multiple semi-parallel code executions.
Like the synchronous networkRequest.X() functions but asynchronous. So, it immediately continues with the next code instructions and does not block the execution.
The functions return a Promise with { response, body} object.
Therefore, you can use await, then(), catch() or finally().
Pausing behavior is the same as for networkRequest.X().
| API | |
|---|---|
.getAsync( "<url>", [<{options}>]): Promise<{ response, body }> | Sends a GET-Request to a URL |
.postAsync( "<url>", <{body}>, ["<content-type>"], [<{options}>]): Promise<{ response, body }> | Sends a POST-Request to a URL with a body (Object or String) |
.putAsync( "<url>", <{body}>, ["<content-type>"], [<{options}>]): Promise<{ response, body }> | Sends PUT-Request to URL with a body (Object or String) |
.deleteAsync( "<url>", [<{options}>]): Promise<{ response, body }> | Sends a DELETE-Request to a URL |
.headAsync( "<url>", [<{options}>]): Promise<{ response, body }> | Sends a HEAD-Request to a URL |
Example Code
networkRequest.getAsync(
'https://www.proceed-labs.org/',
{
headers: {
'user-agent': 'PROCEED-ENGINE/1.0.0'
},
rejectUnauthorized: true,
},
).then(
({ response, body }) => {
console.info("Request successful: " + body.slice(-7));
console.log(response);
}
).catch(({ response, body }) => {
console.info("Request NOT successful: " + body.slice(-7));
console.log(response);
}).finally(() => {
console.info("\n\nRequest FINAL\n\n");
});networkServer: create a listening HTTP Server
TODO
| API | |
|---|---|
.get( "path" ): { req, res } | TODO |
.post( "path" ): { req, res } | TODO |
.put( "path" ): { req, res } | TODO |
.delete( "path" ): { req, res } | TODO |
.getAsync( "path" ): Promise<{ req, res }> | TODO |
.postAsync( "path" ): Promise<{ req, res }> | TODO |
.putAsync( "path" ): Promise<{ req, res }> | TODO |
.deleteAsync( "path" ): Promise<{ req, res }> | TODO |
.get( "path", [<clb()>] ): void | TODO |
.post( "path", [<clb()>] ): void | TODO |
.put( "path", [<clb()>] ): void | TODO |
.delete( "path", [<clb()>] ): void | TODO |
.close(): void | TODO |
Example Code
Trigger Events
throw new BpmnError( ["<reference>",] "explanation" )
| API | Send network requests |
|---|---|
'reference' | Optional, a String that is matched to the corresponding errorCode of the error element (prio 1) or to the name attribute of the attached BPMN boundary error event (prio 2). If there is no match but an attached event without a name, then the flow is given to this Event. See Error and Escalation Event description |
'explanation' | A String that is stored in the logging system of the Engine. |
throw new BpmnEscalation( ["<reference>",] "explanation" );
| API | Send network requests |
|---|---|
'reference' | Optional, a String that is matched to the corresponding escalationCode of the escalation element (prio 1) or to the name attribute of the attached BPMN boundary escalation event (prio 2). If there is no match but an attached event without a name, then the flow is given to this Event. See Error and Escalation Event description |
'explanation' | A String that is stored in the logging system of the Engine. |
Example
const capabilities = getService('capabilities');
const network = getService('network');
await setTimeoutAsync(() => {
log.info('Script started with a short delay');
}, 5000);
const amount = variable.get('amount');
log.info("The value of the process variable 'amount' is: " + amount);
if (typeof amount === 'number') {
variable.set('amount', ++amount);
log.info("Increased variable 'amount' by 1");
} else {
variable.set('amount', 1);
log.info("Set variable 'amount' to 1");
}
// send get-request using given url and store response body in variable
try {
const { response, body } = await network.get('http://localhost:33029/status');
log.debug(`Successful GET request with response: ${response.statusCode}`);
log.info(`Engine Status is: ${body}`);
variable.set('requestedData', body);
} catch (error) {
if (error.response) {
log.error('GET Response was not successful. Status Code: ' + error.response.statusCode);
} else {
log.error('An error occured in the GET request: ' + error.message);
}
}
// set current progress of script task to 50%
setProgress(50);
// send put-request using given url and data
const exampleText = '<task>A Simple XML element</task>';
try {
const { response, body } = await network.put(
'https://httpbin.org/anything',
exampleText,
'text/xml',
{
headers: {
'My-New-Header': 'Sent from PROCEED',
},
},
);
log.debug(`Successful PUT request with response code: ${response.statusCode}`);
log.debug(`Successful PUT request with response body: ${body}`);
} catch (error) {
if (error.response) {
log.error('PUT Response was not successful. Status Code: ' + error.response.statusCode);
throw new BpmnEscalation('BAD CODE given back');
} else {
log.error('An error occured in the PUT request: ' + error.message);
throw new BpmnError('An Error 101', 'It seems there is no Server');
}
}
// check if service is available, return true if so
function checkState() {
const { response, body } = await network.get('https://exampleservice.org/status');
if (body.available) {
log.info('Service is available!');
return true;
} else {
log.info('Service is not available! Test again');
return false;
}
}
// request service status every second, end interval if service is available
try {
await setIntervalAsync(checkState, 1000);
log.info('Service is available');
} catch (error) {
if (error.response) {
log.error('GET Response was not successful. Status Code: ' + error.response.statusCode);
} else {
log.error('An error occured in the GET request: ' + error.message);
}
}
const image = await capabilities.startCapability('takePhoto');
log.info('Photo taken');
// set variable with new value
return { photo: image };