Script Activities

This document covers the MDW script activities (labeled "Execute Script" and "Expression Evaluator" in the Toolbox). Script expression syntax can also be used in other places throughout MDW.

Supported Languages

MDW has built-in support for these scripting languages: In addition, you can implement support for any arbitrary scripting language as described below.

When you drag the general scripting activity onto your process canvas, the first configuration attribute you'll specify is the the language to use. In MDW Studio, this appears as a dropdown on the Script tab in the properties view for an "Execute Script" activity, or on the Expression tab for a "Script Expression Evaluator".

Groovy is the recommended general-purpose scripting language for MDW. Groovy, Kotlin, Python and JavaScript are all supported out-of-the-box through Java's generic ScriptEngine mechanism. Check the scripting-related automated tests for detailed working examples of all three scripting languages.

Kotlin specifics are described here: https://github.com/CenturyLinkCloud/mdw/blob/master/mdw-workflow/assets/com/centurylink/mdw/kotlin/readme.md.
Python specifics are described here: https://github.com/CenturyLinkCloud/mdw/blob/master/mdw-workflow/assets/com/centurylink/mdw/python/readme.md.

Whichever scripting language you choose, the activities behave similarly, with the main difference being the syntax of the script itself. The script content is stored as an attribute of your activity, so it is maintained and versioned along with your process definition. To edit your script, you can right click on the activity and select "Edit Script" from the context menu, or click on the "Open" link in the configurator "Script" tab.

In your script you have implicit access to all of your process variables, as well as "runtimeContext" (which represents the containing activity's workflow state). The runtimeContext binding is an instance of ActivityRuntimeContext. The syntax for accessing your process variables is simply varName in Groovy or JavaScript. In Kotlin, variables are referenced through the variables map.

Execute Script Activity

In a script executor activity, you can both interrogate and assign values to your process variables. Document variables are treated specially, however, and you'll need to identify which if any document (or Reference) variables are to be assigned values in your script:



You can control the return code from your script executor activity by returning a value from your script. For example, if your activity has two outcomes labeled "VALID" and "INVALID", and your script has business logic that determines the outcome, you could implement as follows:
if (myVar != null && myVar.indexOf("something important") >= 0)
  return "VALID";
else
  return "INVALID";

Script Expression Evaluator

A script evaluator behaves much like a script activity except that it is normally a simple, one-line statement that evaluates to the return code which controls the outcome of the activity. It is used for clarity to indicate a decision point in your process flow, where the outcome will depend on the runtime value of one or more process variables:

Logging

MDW supports various logging frameworks including SLF4J, SimpleLogger, Log4J, STDOUT, and others. Whichever of these loggers you choose, within your script activities you can hook into special functionality that will include helpful tags in your logging output enabling you to identify runtime information regarding the source of your log lines. Here's an example log line from an activity implementor:
[p255409661.10034 a3.10139] Here is my important log output
In this log line the special tag [p255409661.10034 a3.10139] identifies the processId, processInstanceId, activityId and activityInstanceId where the logging comes from. Important: To take advantage of this special log tagging, you'll need to write your log output by using the implicit runtimeContext available in your script: Furthermore, if you use this recommended logging pattern within your dynamic Java activity, your log lines will show up in MDWHub's logging views as illustrated in the following screenshot.



Script Libraries

Script libraries can contain reusable logic and utility classes that are accessible from all your script activities. A script library artifact is really nothing more than a segment of code that resides in an MDW package. Currently the only supported language for script libraries is Groovy. Namespace resolution considerations dictate that the Groovy package name for your library components be the same as your MDW package name, and for this reason only MDW packages that comply with Groovy naming rules may contain script libraries. To create a new script library artifact, right click on the MDW package in Process Explorer view, and select New > Script. The newly-created script will automatically contain the appropriate package declaration. Here's an example:
package ValidationLibrary;

class TnValidator
{
  boolean validate(tn)
  {
    println 'tn: ' + tn;
    return true;
  }

  Closure getRegisterTnClosure()
  {
    return println('registering tn: ' + it); }
  }
}
This resides in the MDW package ValidationLibrary and contains a class declaration for TnValidator. To access this functionality from a script activity, you might include the following code:
  import ValidationLibrary.*;
  ...
  tnVal = new TnValidator();
  valid = tnVal.validate(travelerTN);

  tns = ["303-555-1212", "303-634-7861", 303-624-1952];
  tns.each(tnVal.getRegisterTnClosure());

Script library artifacts are cached in the MDW runtime engine. They are compiled on-demand by the GroovyScriptEngine. The first time any Groovy script is accessed, all script libraries are loaded and initialized. So the first execution may be slow, but subsequent executions should be very fast since the code has been pre-loaded and pre-compiled. If you change a script or library and save it and sync the server cache, the next access will re-initialize the libraries.

Debugging Groovy Scripts

IntelliJ has Groovy support built in. If you have the Groovy Plug-In http://dist.springsource.org/snapshot/GRECLIPSE/e4.6 installed on your Eclipse, you can debug your script activity or library by opening the contents and setting a breakpoint according to the usual procedure in Eclipse. This only works for local (not remote) workflow projects, and the server must be running in debug mode. When a breakpoint is encountered, you can evaluate variables and change values just as you would when debugging Java code in IntelliJ/Eclipse. Note that in the context of a script activity, there is a wrapper class that contains your process variable bind values. You can evaluate or watch a process variable value by entering the following expression in IntelliJ/Eclipse:
this.getBinding().getVariable("myVariable")
this.binding.getVariables().get("modifiedXmlBean")

Custom Scripting Languages

You can add support in MDW's script activities for any language of your choosing by writing a lightweight wrapper around your script library. To accomplish this, you need to create assets that implement either or both of two interfaces:
  • ScriptExecutor
  • ScriptEvaluator


  • The Java 1.8 javax.script.ScriptEngine interfaces makes it easy to plug-in a script provider who complies with the JSR 223 specification. MDW's KotlinExecutor is implemented as an asset, and you can refer to this as an illustration of how to implement your own executor. The main point to observe is the @RegisteredService annotation, which is how the runtime engine identifies your implementation as an available language. To add a custom scripting activity to the Toolbox, create a .impl asset similar to the Kotlin ScriptActivity. The details of configuring activity implementors are described here.