Please enable JavaScript to view this site.

InterFormNG2 Manual

The advanced, special workflow component, Run a script can be used in order to call a script from the workflow.

 

The JavaScript execution engine supports ECMAScript v5.1 with the addition of the following ECMAScript 6 features:

 

The keywords "let" and "const" can be used.

 

When variables are declared with let or const, the ECMAScript 6 scope rules are used.

 

The component has these parameters:

 

NG2RunScript0001

 

Scripting language

The language in which the script is to be written. Currently only JavaScript can be selected.

 

 

Script resource

This should select the script from the others Library folder (or subfolder) in which the script is to be loaded.

 

 

Note that the objects that are specific to JavaScript being run in a browser, are not available. For instance "window" and "document" are not defined.

One exception is the "console" object which is available in a limited version. The console object can be used to write to the workflow job log. For instance:

console.log("Info message");

Will write an info message to the job log.

The following methods are available on the console object for logging with different log levels:

 

   log()

   info()

   warn()

   error()

   debug()

   trace()

 

It is possible to load other JavaScript files into the script by using the load() function. The argument can be a URL or a file system path. Note that file system paths have to be the path on the operating system's file system, not the path within the InterFormNG2 virtual file system. The full path to the file should be used. If the underlying operating system is Windows, then double-backslash (\\) can be used as backslash in the file name. Alternatively single slash (/) can always be used.

 

Example:

load("C:/ProgramData/InterFormNG2/resources/home/other/script/otherjs.js");

Accessing workflow variables and payload

 

Workflow variables

All workflow variables can be used as global variables within the JavaScript code. Note however that a lot of the pre-defined workflow variables contain a dot (.) character. This is not allowed in JavaScript variable names, so for all variable names the dot will be replaced with an underscore (_). Apart from that, it is your own responsibility to ensure that workflow variables have names that are valid in JavaScript (most importantly you should avoid variable names that are reserved words in JavaScript).

Note that if you set a JavaScript variable to a numeric value, it will become a floating point number in the workflow variable, even if an integer value has been set. This can be important to know when comparing the value.

 

Please notice, that the global values of the script are mixed with the workflow variables. The advantage is, that the workflow and the script can exchange information in that way (apart for the payload), so that the script can read the values set prior to the call of the script and the script can change the values of the workflow variables, which are used in the subsequent workflow components.

 

You should however also ensure, that you might not by accident share the same name of a workflow variable and then change the value in the script, which of course can considered as a problem, if this share of a variable was unintended.

 

 

The payload

The workflow payload will be available for JavaScript as an object with the name "payload". Note that if you have a workflow variable with the name "payload", then that variable will not be accessible in the script. Since the payload can be either a text string or binary data, the payload object has a number of methods that need to be used to read/write the payload. Note that if you directly change the payload object reference itself, then the payload will be invalidated.

 

The following methods are available on the payload object:

 

toString(): Returns the payload as a string. Assumes UTF-8 encoding of the string content.

 

toString(encoding): Return the payload as a string, encoded with the specified encoding. The encoding argument must be an encoding identifier that is valid in Java.

 

toBinary(): Returns the payload as a byte array.

 

setString(newPayload): Sets a new string as the payload. The newPayload must be a UTF-8 encoded string.

 

setString(newPayload, encoding): Sets a new string as the payload. The string will be encoded with the specified encoding. The encoding argument must be an encoding identifier that is valid in Java.

 

setBinary(newPayload): Sets a new byte array as the payload. newPayload must be a byte array.

 

payload.xpath(xpath): This method can only be used when the payload is an XML document. The method will execute an XPath expression on the payload and return the result. The XPath expression has to refer to an atomic value (i.e. the method cannot return a node-set). If the XPath expression is invalid or the payload cannot be parsed as XML, then this method will return null. The parameter must be setup as a string. The Xpath expression must be enclosed in double quotes like so: var DocType = payload.xpath("ng:trim(/Root/CompanyInfo/DocType)");

 

 

Configuration

To make it possible to execute JavaScript code in a workflow, the system settingAllow script execution in workflows” must be enabled. To change this setting, log in as administrator and change the setting under Other → System.

 

 

Security considerations

From a security perspective we recommend that scripting is only enabled when workflow requirements can only be achieved through scripting.

Before enabling scripting support, be aware of the following security implications:

 

The JavaScript load function can be used to load JavaScript files from the file system. On a multi-tenant setup that uses the file system for resources, this will allow a tenant to load and execute JavaScript files that are stored in another tenant's resource folder.

 

JavaScript is a general programming language with infinite possibility. InterFormNG2 sets some boundaries for what is possible in the scripts, but creative people may still be able to exploit loopholes.

 

 

Examples of how you can use the scripts are included below:

 

1.Example1: Count the digits in a text payload.

2.Example2: Select printer with complex rules

3.Example3: Evaluate an Xpath expression stored in a variable or node

4.Example4: Alternative to a script - extract XML payload from sub-node.

 

 

Example 1: Count the digits in a text payload.

The following is an example of a script that can be executed in the workflow. This script counts the number of digits in a textual payload. The result is written to the job log.

 

function countDigits(str)

{

 let numDigits = 0;

 for (i = 0; i < str.length; i++)

 {

   if (str.charAt(i) >= '0' && str.charAt(i) <= '9')

     numDigits++;

 }

 return numDigits;

}

 

var totalDigits = countDigits(payload.toString());

 

console.log("The payload contains " + totalDigits + " digits");

 

 

Example 2: Select printer with complex rules

Another example, where a Javascript can be called is e.g. to setup a long, advanced list of conditions e.g. to setup output variables e.g. for which printer to use for the merged result. Here the workflow can e.g. setup a normal, default printer and then we can call a Javascript with a lot of conditions to test for scenarios, where the default printer should be overridden.

 

This workflow is used:

 

 

NG2Javascript001

 

 

It consists of these components:

 

NG2Javascript003

 

NG2Javascript002

 

NG2Javascript004

 

NG2Javascript005

 

 

So in short: The workflow reads an input XML file from a folder. The default printer is saved into the workflow variable, Printer. Then the javascript is called, which might change the value of the workflow variable, Printer. Finally the input file is merge with a template and printed on whatever printer, that is selected.

 

The input file has a header, that looks like this:

 

NG2Javascript006

 

In the script we want use the valued for the user node and the DocType node to determine if another printer is to be selected.

 

The Javascript looks like this:

 

var Printer;

var User = payload.xpath("ng:trim(/Root/CompanyInfo/user)");

var DocType = payload.xpath("ng:trim(/Root/CompanyInfo/DocType)");

 

if (DocType == "Invoice") Printer="Printer1";

if (DocType == "CreditNote") Printer="Printer2";

 

if (User == "KSE") Printer="Printer3";

 

 

The script does this:

1.This script refers to the workflow variable, Printer.

2.The variable, User is defined as the contents of the node: /Root/CompanyInfo/user from the input file.

3.The variable, Doctype is defined as the contents of the node: /Root/CompanyInfo/DocType from the input file.

4.If the DocType is "Invoice", then Printer1 is selected via the workflow variable, Printer.

5.If the DocType is "CreditNote", then Printer2 is selected via the workflow variable, Printer.

6.If the user is "KSE" (who works from home), the the printer should always be Printer3 - for all document types.

 

If none of the conditions above are true, then the default Printer is used.

 

The final workflow component, Print use the printer, that was selected via the workflow variable, Printer.

 

 

Example3: Evaluate an Xpath expression stored in a variable or node

One of the 'magic' things, that you can do with java scripts is, that you evaluate an XPath expression which is dynamic i.e. that the XPath itself is dynamic and e.g. found in a node in an input XML file.

 

To illustrate how that can be done we can consider this input XML file:

 

 

<?xml version="1.0" encoding="UTF-8"?>

<test>

 <data>

         <name>John Smith</name>

         <customerNo>123456789</customerNo>

 </data>

 

 <expressions>

         <expression1>/test/data/name</expression1>

         <expression2>concat(/test/data/name, ' ', /test/data/customerNo)</expression2>

 </expressions>

 

</test>

 

 

The XML file contains a data section and an expression section.

 

The expression section contains the two dynamic XPath expressions, that we want to evaluate/calculate in the script.

 

This is here done with two sections like the one below:

 

NG2RunAScript0002

 

The two elements are these:

 

In the first we extract the value (XPath expression to execute in the script) into the variable, myXpath. This sets the value (with the input XML file above) to:

"concat(/test/data/name, ' ', /test/data/customerNo)", which is the XPath expression, that we want to execute:

NG2RunAScript0003

 

 

In the second we call the script via the Run a script component:

NG2RunAScript0004

 

 

And we can of course also run the script once more after changing the myXpath variable to the value from the expression 1 node in the input file, which results in the value, "/test/data/name", which is another XPath expresssion to run.

 

The referenced script is here setup like below:

 

 

console.log("xpath expression: " + myXpath);

 

var xpathResult = payload.xpath(myXpath)

 

console.log(xpathResult);

 

 

The script outputs the expression, that it is going to execute. Then the expression found in the variable, myXpath is executed and finally the executed result is output. If you run the workflow described here, then you can see the result in the job log:

 

NG2RunAScript0005

Note: The job log is built from the bottom and up.