Automation

Automation Scripting

Updated: July 17, 2023

 

Extract from the course "Applying Business Logic" at Hyland University

Automation Scripting is a Nuxeo module which provides ability to create and contribute Automation chain/operation in JavaScript.

This enables you to benefit from:

  • Loops
  • Conditions
  • Smooth Automation implementation maintenance

7.3 Changes

In 7.2, Context ctx was in run function signature:

function run(ctx, input, params) {...... your code ......}

Since 7.3, this parameter has been removed and is still available in script. To align on 7.3, please remove it from your script as:

function run(input, params) {...... your code ......}

Requirements

Automation Scripting is using Java 8 Nashorn engine. To leverage all the Automation Scripting feature, the Nuxeo server needs to run at least JDK 8 update 40.

How It Works

Nuxeo Automation Scripting allows you to write JavaScript code to use Automation operations and chains programmatically:

  • The whole script must be wrapped into the run() function

    /**
     * Wrapper function for the whole script
     *
     * @param {org.nuxeo.ecm.automation.OperationContext} ctx The operation context.
     * @param input The automation input.
     * @param params The parameters of your different operations.
     */
    function run(input, params) {
    ...... your code ......
    }
    
  • Passing parameters and variables through the operation context and input.

  • Using operations/chains as JavaScript functions within this run() function

    // For instance, the operation to display JSF messages
    WebUI.AddMessage(input, {
        /*required:true - type: string*/
        'message': "Display It!" ,
        /*required:true - type: string*/
        'severity': "INFO"
    });
    
  • Using for/if/print or any other JavaScript feature

      if(docs.length > 3){
        var index;
        for (index = 0; index < docs.length; ++index) {
            Document.SetProperty(docs[index], {
              /*required:true - type: string*/
              'xpath': "dc:title" ,
              /*required:false - type: boolean*/
              'save': true,
              /*required:false - type: serializable*/
              'value': "renamed"
        });
      }
    
  • Operation Context can be used to read or write variables through ctx JavaScript object:

    function run(input, params) {
    
        var root = Repository.GetDocument(null, {
            "value" : "/"
        });
    
        var newDoc = Document.Create(root, {
            "type" : "File",
            "name" : "newDoc",
            "properties" : {
                "dc:title" : ctx.WorkflowVariables.var,
                "dc:description" : ctx.NodeVariables.var
            }
        });
    
        return newDoc;
    }
    

If one of your Automation chain or operation contains dashes in their names/ids, Nuxeo Automation will prevents those characters and replaces with underscore:

Example:

Automation chain id: my-chain-with-dashes

Automation scripting usage: var document = my_chain_with_dashes(input, {.......});

Example

The following code example bound to a simple action button, rename all selected documents with the value "test" as dc:title or displays a warning JSF message (depending on the number of the selected documents).

As a result, once the Automation Scripting code has been bound to a simple action button, we can rename all the selected documents or display a warning message.

Binding Automation Scripting to Action/Listener/Workflow

For 7.2 target Platform, Automation Scripting feature allows Studio users to bind their JavaScript contribution to actions, listeners or workflows.

Action Binding

To bind an Automation JavaScript to an action:

  1. Create your action.
  2. In the Action Execution, select your custom operation.

Automation Chain Binding

  • Automation Scripting scripts can be executed within an Automation Chain, by using the operation Execution Flow > Run Chain. The ID must be formatted as javascript.script_name.
  • Automation Scripting custom scripts can be used as well directly in Automation Chains from the category Scripting as follow:

REST Call

Automation scripts can be called like any operation or chain using the Automation HTTP bridge. See cURL sample.

Helpers

Platform Functions Helpers are available in Automation Scripting.

You can use (like in MVEL expression) functions as follow:

Fn.getEmail("Administrator")

Helper contributions are available to create custom functions to use directly in Automation Scripting and Mvel.

Logging - Debugging

When printing values as follow, the output is redirected to the console:

print("value")

But you can also use the helper "Console" to write logs within NUXEO_HOME/log/server.log:

Console.info("Informations");
Console.warn("Warnings");
Console.error("Errors");

Getting Value From a Context Variable

To get the value of a Context Variable you should use the following syntax:

ctx.get('var')

Metrics

Since 7.2, metrics have been added to Automation Scripting services to monitor Nashorn performances with the Nuxeo Platform.

To activate the metrics, set the following variable in nuxeo.conf:

automation.scripting.monitor.enable= true

Or set the Log4J level to TRACE for org.nuxeo.automation.scripting.internals.AutomationScriptingComponent .

This feature gives the ability to get time execution informations through JMX: org.nuxeo.StopWatch.

Restrictions

Since 7.3, Java imports in Javascript: all Java imports are forbidden by default into the Nuxeo Platform.

var file = Java.type("java.io.File");
print(file);

This example cannot be applied anymore.

Advanced Use

Using the Automation Scripting Service

The AutomationScriptingService provides API to run your JavaScript codes within the Nuxeo Automation engine:

AutomationScriptingService

package org.nuxeo.automation.scripting.api;

import javax.script.ScriptException;

import org.nuxeo.automation.scripting.internals.ScriptRunner;
import org.nuxeo.ecm.core.api.CoreSession;

public interface AutomationScriptingService {
.....

    /**
     * Run Automation Scripting with given 'JavaScript' InputStream and CoreSession.
     * @param in
     * @param session
     * @throws ScriptException
     */
    void run(InputStream in, CoreSession session) throws ScriptException, OperationException;

    /**
     * Run Automation Scripting for a given 'JavaScript' script and CoreSession.
     * @param script
     * @param session
     * @throws ScriptException
     */
    void run(String script, CoreSession session) throws ScriptException, OperationException;

......
}

Usage:

Example

ScriptRunner runner = scriptingService.getRunner(session);
assertNotNull(runner);

InputStream stream = this.getClass().getResourceAsStream("/simpleAutomationScript.js");
assertNotNull(stream);
runner.run(stream);

Contributing Automation Scripting Operations

Automation scripting operation is made through an XML contribution on the operation extension point:

<extension target="org.nuxeo.automation.scripting.AutomationScriptingComponent" point="operation">
  <scriptedOperation id="Scripting.TestBlob">

    <!-- Define input type (input field in the run function) -->
    <inputType>Blob</inputType>

    <!-- Define output type (the return object) -->
    <outputType>Document</outputType>

    <!-- Define operation category (by default 'javascript') -->
    <category>javascript</category>

    <!-- Define parameters to use through the params field of the run function -->
    <param name="document" type="string"/>

    <!-- Define the JavaScript code wrapped into run function surrounded by CDATA -->
    <script>
      function run(input, params) {
          var root = Repository.GetDocument(null, {
              "value" : "/"
          });
          var newDoc = Document.Create(root, {
              "type" : "File",
              "name" : "newDoc",
              "properties" : {
                  "dc:title" : "New Title",
                  "dc:source" : "JavaScript",
                  "dc:subjects" : [ "from", "javascript" ]
              }
          });
          var blob = Blob.AttachOnDocument(input, {
              "document" : params.document
          });
          Log(null, {
              "message" : "LogOperation is working so much - Blob title:"+blob.filename,
              "level" : "info"
          });
          print("title:"+blob.filename);
          return newDoc;
      }
    ]]></script>
  </scriptedOperation>
</extension>

Automation scripting operations can be used as common Automation operations:

  • Using it within chains, for instance:

    The JavaScript Operation Definition

    <scriptedOperation id="javascript.HelloWorld">
      <inputType>string</inputType>
      <outputType>string</outputType>
      <param name="lang" type="string"/>
      <script>
        function run(input, params) {
          if (params.lang === "fr") {
            return "Bonjour " + input;
          } else {
            return "Hello " + input;
          }
        }
      </script>
    </scriptedOperation>
    

    The Chain Definition

    <extension point="chains" target="org.nuxeo.ecm.core.operation.OperationServiceComponent">
      <chain id="Scripting.ChainedHello">
        <operation id="javascript.HelloWorld">
          <param type="string" name="lang">fr</param>
        </operation>
        <operation id="javascript.HelloWorld">
          <param type="string" name="lang">en</param>
        </operation>
      </chain>
    </extension>
    

  • Using it directly from the Automation Service:

    OperationContext ctx = new OperationContext(session);
    Map<String, Object> params = new HashMap<>();
    
    params.put("lang", "en");
    ctx.setInput("John");
    Object result = automationService.run(ctx, "Scripting.HelloWorld", params);
    assertEquals("Hello John", result.toString());