By placing a [Script Task] in the middle of the Workflow diagram, data editing by ECMA Script is possible. You can automate processing of string editing for example, by calculating the working hours between "Start time" and "Finish time", or automatically adding the day of the week information to the 'Operation date'. (You can achieve more complex processing than by using [Service Task (Data Assignment)].)
1. Usage Example of Script Task
- 1. Data Assignment
- Automatic assignment of date or numbers which are generated by ECMAScript
- 2. Data Editing
- Editing the entered values and strings, and then assigning them as new data.
- "ECMA Script" is a scripting language that is standardized based on the common parts of JavaScript and JScript
2. Functions available in Script Task
- a. Recommended JavaScript
- All specifications defined in "ECMA-262, Edition 3" (JavaScript 1.5)
- b. Available JavaScript
- Many specifications defined in "ECMA-262, Edition 5" and "Edition 6"
- c. Available Java class
- Java classes that are required to access business data, etc.
- Basic knowledge of JavaScript and Java will be needed
R2300: Functions available in Script Task
3. Setting Script Task
- 1. Register the ECMA Code
- Enter the processing code, such as Data reference, Data processing, Data assignment, etc.
- 2. Select a script engine
- Select either of "Nashorn" (default) and "Rhino"
- Assignment or updating of Business data is performed collectively after the completion of script processing
- Updating and assignment will not be performed in the event of an error (Proceeds to the next Step)
- You can also specify different destinations in the event of an error or successful processing. (Error Boundary Event)
- Processing time of the Script is limited to a maximum of 30 seconds (but will vary slightly according to the load condition)
- HTTP requests must be up to 10 per one automatic Task
//// == Data Retrieving == var dataA = engine.findDataByNumber("0") + ""; // Retrieving data 0 var dataB = engine.findDataByNumber("Data B") + ""; // Retrieving data with the name of "Data B" // convert java.lang.String → javascript string //// == Calculating == var newData = dataA + dataB; //// == Data Updating == engine.setDataByNumber("3", newData ); // Data Updating
R2301: Script Data Retrieving / Assignment
R2252: OAuth Token Getting Procedure
Config. Items: Script Task
X. Blog Articles
- 2018-05-09: Using Log Output for Debugging of Script Task
- 2018-07-17: Sending a Text Message in the Middle of Workflow Using SMS – Script Task version
X. BPMN Icons
- 2019-04-25: Script Task
X. Business Apps
- PayPal Billing Process
- Customer Master Data Sync Process
- Answer Drafting Flow
- Catalogue Request Correspondence Flow
- Translation Request Flow
- 外部 API を利用したデータ取得
- Inquiry Handling Process
- Invoice Issuance-Sampling Check
- Employee Information Acceptance
- Boss Evaluation by Ballot
- Common Password Request
Z. More Info: Script Execution Engine
- a. Rhino Engine
- [Script Step] is processed with "Rhino", the JavaScript engine (Server-side)
- b. Feature of Rhino
- Workflow App designers can set an automatic processing script not only by "ECMAScript" (JavaScript) but also by "Java methods". (Scripting Java). For example, if you generate an object in a format such as
new java.lang.String ("kyoto")
, it is possible to use methods of Java String class, such asreplaceFirst ()
. - c. Retrieving Data on Workflow
- To retrieve Business data, such as "Billing Date" or "Estimated Price", make use of a special method of
data.get("♦Data Definition ID♦")
engine.findDataByNumber("♦ITEM ID♦")
. As it calls as a Java instance, an explicit type conversion likevar text = data.get("♦Data Definition ID♦") + "";
var text = engine.findDataByNumber("♦ITEM ID♦") + "";
is recommended when you handle as a JavaScript string/object. [accordion][accordion_item title="TYPEOF test - for Rhino ECMA engine"]/// TYPEOF test - for Rhino ECMA engine var workflowData = engine.findDataByNumber("0") ; var teststring = ""; teststring += "-- primitive Number -- \n"; teststring += typeof 99 + "\n"; // 'number' teststring += typeof 9.99 + "\n"; teststring += typeof Infinity + "\n"; teststring += typeof NaN + "\n"; teststring += typeof Number(9) + "\n"; teststring += "-- primitive String -- \n"; teststring += typeof "" + "\n"; // 'string' teststring += typeof "Questetra" + "\n"; teststring += typeof (typeof 99) + "\n"; teststring += typeof String("ECMA") + "\n"; teststring += "-- Object -- \n"; teststring += typeof new Number(9) + "\n"; // 'object' teststring += typeof new String("ECMA") + "\n"; teststring += typeof new java.lang.String("ECMA") + "\n"; teststring += typeof workflowData + "\n"; teststring += typeof engine.findDataByNumber("0") + "\n"; teststring += typeof new com.questetra.bpms.core.model.formdata.ListArray() + "\n"; teststring += "-- XML -- \n"; teststring += typeof <foo bar="BAR">FOO</foo> + "\n"; // 'xml' teststring += typeof XML('<foo bar="BAR">FOO</foo>') + "\n"; teststring += typeof new XML('<foo bar="BAR">FOO</foo>') + "\n"; teststring += "--- additional info --- \n"; teststring += typeof true + "\n"; // 'boolean' teststring += typeof undefined + "\n"; // 'undefined' teststring += typeof [1, 2, 4] + "\n"; // 'object' teststring += typeof /s/ + "\n"; // 'object' teststring += typeof null + "\n"; // 'object' (not 'null') teststring += typeof function(){} + "\n"; // 'function' // teststring += typeof Symbol() + "\n"; // ERROR (not 'symbol') engine.setDataByNumber( "0", teststring );
INSTANCEOF test - for Rhino ECMA enginetestX <- String("BPMS") testX is NOT instanceof String testX is NOT instanceof java.lang.String testY <- new String("ECMA") testY is instanceof String testY is NOT instanceof java.lang.String testZ <- new java.lang.String("JAVA") testZ is instanceof String testZ is instanceof java.lang.String test1 <- engine.findDataByNumber( "8" ) test1 is instanceof String test1 is instanceof java.lang.String test1b <- engine.findDataByNumber( "8" ) + "" test1b is NOT instanceof String test1b is NOT instanceof java.lang.String test2 <- engine.findDataByNumber( "9" ) // Select test2 is NOT instanceof String test2 is NOT instanceof java.lang.String test2 is instanceof java.util.ArrayList
- d. Update Data on Workflow
- To update Data on Workflow with the value calculated at a Script Step, make use of a special method
retVal.put("♦Data Definition ID♦","♦New Value♦")
engine.setDataByNumber("♦ITEM ID♦","♦NEW VALUE♦")
. (You must explicitly describe "java.math.BigDecimal" to return the result of the calculation in the script to the Workflow side, for there exists only "number type" in ECMA/JavaScript type for numerical values.) - e. Function and Sample Codes Useful for your Business
- number Math.random(); // Random Number (0.00 to 0.99)
//////// == Calculating == var myrand = Math.floor( Math.random() * 5 ) ; // 0 or 1 or 2 or 3 or 4 //// == Updating == engine.setDataByNumber("♦DataDefID♦", new java.math.BigDecimal(myrand) );
[/accordion_item][accordion_item title="number dateObj.getTime(); // Elapsed time in milliseconds (since 1970-1-1, 0:00 UTC)"]//// == Retrieving == var timestart = engine.findDataByNumber("♦DataDefID♦"); // Datetime type:Process Start time var timesent = engine.findDataByNumber("♦DataDefID♦"); // Datetime type:Reply e-mail transmission time //// == Calculating == var conciergesec = timesent.getTime() - timestart.getTime(); var conciergehour = new java.math.BigDecimal( Math.floor( conciergesec / (1000 * 60 * 60) )); // Math.floor Rounding //// == Updating == engine.setDataByNumber("♦DataDefID♦",conciergehour); var daystart = timestart.getDay(); // Memo of day of the week of inquiry occurrence if (daystart == 0) engine.setDataByNumber("♦DataDefID♦","Sunday"); if (daystart == 1) engine.setDataByNumber("♦DataDefID♦","Monday"); if (daystart == 2) engine.setDataByNumber("♦DataDefID♦","Tuesday"); if (daystart == 3) engine.setDataByNumber("♦DataDefID♦","Wednessday"); if (daystart == 4) engine.setDataByNumber("♦DataDefID♦","Thursday"); if (daystart == 5) engine.setDataByNumber("♦DataDefID♦","Friday"); if (daystart == 6) engine.setDataByNumber("♦DataDefID♦","Saturday");
string stringObj.charAt(number intindex); // N-th character (Leftmost is 0-th)//// == Retrieving == var mynumber = engine.findDataByNumber("♦DataDefID♦") + ""; //// == Calculating == if( mynumber.length == 13 ){ var mysum = 0; for( i=1; i<13; i++){ mysum += parseInt( mynumber.charAt(i) ) * (i % 2 + 1); } var checkdigitnum = 9 - mysum % 9; var typedcd = parseInt( mynumber.charAt(0) ); //// == Updating == if( typedcd == checkdigitnum ){ engine.setDataByNumber("♦DataDefID♦", "OK" ); } else { engine.setDataByNumber("♦DataDefID♦", "ERROR" ); } }
string JSON.parse(String text); // Data retrieving from JSON//// == Retrieving == var weatherjson = JSON.parse(engine.findDataByNumber("♦DataDefID♦")); // In assumption of already obtained in an Intermediate Event, etc. //// == Calculating == var mydesc = weatherjson.list[0].weather[0].description; var mytemp = new java.math.BigDecimal(weatherjson.list[0].temp.max - 273.15); //// == Updating == engine.setDataByNumber("♦DataDefID♦", mydesc ); engine.setDataByNumber("♦DataDefID♦", mytemp );
string stringObj.replace(string regexp_or_patternstr, string newsubstr); // Substitution of String (Regular Expression)//// == Retrieving == var fromaddr = engine.findDataByNumber("♦DataDefID♦") + ""; var inq = engine.findDataByNumber("♦DataDefID♦") + ""; //// == Calculating == var inquirywithmark = inq.replace(/(^.*$)/gm, "> "+"$1"); // Greater-than sign as quotation //// == Updating == engine.setDataByNumber("♦DataDefID♦", fromaddr + '\n' + inquirywithmark );
string[] StringObj.split(String regex_or_separator) // Splitting of Strings//////// == Retrieving == var csv_text = engine.findDataByNumber("♦DataDefID♦"); // In assumption of CSV data (four columns) of String type multiple lines // ex) // Nakagyo-ku, Kyoto-shi, Kyoto-pref, Japan // Malibu, Los Angeles County, California, USA //// == Calculating == var csvObj = new String( csv_text ); // String Object (JavaScript) var tmpTable = new com.questetra.bpms.core.model.formdata.ListArray(); // Table type data var lineArray = csvObj.split("\n"); // Split per each line, storing in array String[] for (var i=0; i < lineArray.length; i++){ var tmpRow = new com.questetra.bpms.core.model.formdata.ListArray.ListRow(); // Added row (horizontal row) var cellstrArray = lineArray[i].split(","); // Split at each comma, and Store to array tmpRow.addCol( cellstrArray[0] ); tmpRow.addCol( cellstrArray[1] ); tmpRow.addCol( cellstrArray[2] ); tmpRow.addCol( cellstrArray[3] ); tmpTable.addRow( tmpRow ); // Add Row } //// == Updating == engine.setDataByNumber("♦DataDefID♦", tmpTable );
String ListArrayObj.get(int row, int col); // Strings inside Table type Data//// == Retrieving == // mytable: com.questetra.bpms.core.model.formdata.ListArray var mytable = engine.findDataByNumber("♦DataDefID♦"); // Retrieving Table type Data //// == Calculating == var i=0; var n = mytable.size(); var texttsv = ""; for (i=0; i < n; i++){ texttsv += mytable.get(i, 0) + "\t"; texttsv += mytable.get(i, 1) + "\t"; texttsv += mytable.get(i, 3) + "\t"; texttsv += mytable.get(i, 4) + "\n"; } //// == Updating == engine.setDataByNumber("♦DataDefID♦", texttsv );
QuserView quserDao.findByEmail(string email); // Search on BPMS User//// == Retrieving == var quserEmail = engine.findDataByNumber("♦DataDefID♦") + ""; // In assumption that "example@example.net" is stored to the Strings data //// == Calculating == // com.questetra.bpms.core.event.scripttask.QuserDaoWrapper var quser = quserDao.findByEmail(quserEmail); //// == Updating == engine.setDataByNumber("♦DataDefID♦", quser);
List<ItemView> itemDao.findAll(String fileName, boolean isSharedFile); // Strings in Options//// == Retrieving == optionsList = itemDao.findAll("value-display-list.xml", true); // M319 Options-XML //// == Calculating == optionsNum = optionsList.size(); var value_id_list = ""; var display_label_list = ""; for (i=0; i < optionsNum; i++){ value_id_list += optionsList.get(i).getValue() + "\n"; display_label_list += optionsList.get(i).getDisplay() + "\n"; } //// == Updating == engine.setDataByNumber("♦DataDefID♦", value_id_list); engine.setDataByNumber("♦DataDefID♦", display_label_list);
List<ItemView> itemDao.findAll(String fileName, boolean isSharedFile); // Assignment of Options into Table Type Data//// == Retrieving == optionsList = itemDao.findAll("value-display-list.xml", true); // M319 Options-XML //// == Calculating == var tmpTable = new com.questetra.bpms.core.model.formdata.ListArray(); // Table type data optionsNum = optionsList.size(); for (i=0; i < optionsNum; i++){ var tmpRow = new com.questetra.bpms.core.model.formdata.ListArray.ListRow(); // Added row (horizontal row) tmpRow.addCol( optionsList.get(i).getValue() ); tmpRow.addCol( optionsList.get(i).getDisplay() ); tmpTable.addRow( tmpRow ); // Add row } //// == Updating == engine.setDataByNumber("♦DataDefID♦", tmpTable );
Comments
0 comments
Please sign in to leave a comment.