Scripting

Quickstart

Five minutes to know which language to pick, where you can write code, and the handful of runtime objects you'll see in every script.

Choose JavaScript or Python

Both are supported as inline scripting languages, but they have very different ceilings:

AspectJavaScript (Nashorn)Python (Jython)
EngineNashorn — JS engine in the JVMJython — Python 2.7 inside the JVM
Available everywhereYes (default)Yes
Java class accessNative — Java.type("…"), importPackage()Native — from java.util import ArrayList
Returning a valueAssign to value, or last expressionscriptResult.setResult(value)
Modern syntaxStandard JavaScriptPython 2.7 only — no f-strings, no print() as statement
Third-party packagesLoad JS libraries via load("…")No pip. No pandas, no numpy, no boto3.
Best forAll inline logic, Java-API-heavy workLightweight scripts when Python syntax is preferred
Need real Python 3?

For modern Python (3.x with pip, virtual environments, full programs), don't use the inline scripting field — use the Execute Script Local or Remote via SSH flow type. That runs a real external Python interpreter and supports pandas, numpy, boto3, etc. The inline script editor is only for small things.

Default recommendation: JavaScript. The rest of this guide and most of the recipes use JS unless Python adds something specific.

Where you can write code

Every place Etlworks shows a scripting text area, you can drop in JavaScript or Python. Common ones:

LocationTypical use
Mapping → field functionCalculate a destination field's value from source fields, or anonymize.
MAPPING → Additional Transformations → FilterReject rows by expression. Returns true (keep) or false (drop).
MAPPING → Additional Transformations → ValidateReject rows or halt the flow with explicit TaskResult codes.
Before Prepare Source Query / Before Extract / For Each Row / After Extract / After LoadFive scripting transformations that run at different points of the source-to-destination pipeline.
Format → PreprocessorModify the raw source message before parsing — fix encoding, fill empty bodies, store the original.
Nested flow → Condition / Loop conditionDecide whether the next step runs, or how many iterations a loop performs.
Execute before / Execute on ExceptionSetup or cleanup hooks attached to a transformation.
Action Conditions (database destinations)Pick INSERT / UPDATE / DELETE / MERGE / nothing per row.
Execute JavaScript or Python flowA dedicated flow type that runs only your code — no source/destination involved.
Dynamic SQL, function parameters, advanced config fieldsAnywhere you see "Open in Editor."

Open the editor

Wherever you see a scripting text area:

  1. Click Open in Editor.
  2. Confirm JavaScript is selected (or change to Python).
  3. Write your script. The editor has syntax highlighting, indentation, and a full-screen mode.

Your first script

The simplest case: a calculated field in Mapping. Click the pen icon next to a destination field, choose Open in Editor, write:

JavaScript
var first = dataSet.getFieldValue(currentRow, 'first_name');
var last  = dataSet.getFieldValue(currentRow, 'last_name');
value = first + ' ' + last;

The same thing in Python:

Python
first = dataSet.getFieldValue(currentRow, 'first_name')
last  = dataSet.getFieldValue(currentRow, 'last_name')
scriptResult.setResult(first + ' ' + last)

Both run for every row of the source dataset and write the result to the destination field. dataSet and currentRow are injected by name — no import needed.

Returning a value

How you return a result depends on the language:

LanguageHow to return
JavaScriptAssign to value, OR rely on the last evaluated expression.
PythonscriptResult.setResult(the_value) — explicit, always required.
JavaScript
// Both work:
value = first + ' ' + last;

// or — last expression becomes the result automatically
first + ' ' + last;

For boolean fields (Filter, Conditions, Loop conditions), return true or false. For Validate, return one of the TaskResult values (see Validate).

Runtime objects

A handful of objects are injected by name into your script. Which ones depend on where you're writing code:

ObjectWhat it isAvailable in
etlConfigCurrent flow's runtime config + key/value storageMapping, scripting transformations, Script flow, almost everywhere
scenarioThe flow's scenario — variables, source/destination registrySame as etlConfig
dataSetThe current source datasetMapping, For Each Row, After Extract, Filter, Validate, Action Conditions
currentRowThe current DataSetRecord being processedFor Each Row, Mapping field functions, Filter, Validate
row0-based row index (integer)For Each Row, Filter, Validate
fieldValueThe field value being calculated (Mapping field functions only)Mapping field functions
messageThe raw source message (Format Preprocessor only)Format → Preprocessor
filterThe CSV row filter objectCSV Format → row filter
destinationThe destination contextAction Conditions
scriptResultWhere Python writes its return valuePython scripts only

Full availability map per location: Reference → Runtime objects.

Logging

Two ways to log from a script:

JavaScript
// Add an info line to the flow log
etlConfig.log("processed " + dataSet.getRecordCount() + " rows");

// Or use the JVM logger directly
com.toolsverse.util.log.Logger.log(
  com.toolsverse.util.log.Logger.SEVERE,
  null,
  "Something went wrong"
);

Lines logged via etlConfig.log(...) appear in the flow's run log alongside platform-emitted entries — searchable from the UI and via tail-flow-log in the CLI.


You're set

From here: