Script-to-Script Bindings
Why you need it — the problem it solves
Large SpEL automations quickly end up copy-pasting common snippets (currency conversion, e-mail templates, date math …). The script-to-script binding lets you refactor that boiler-plate into a single helper script and call it from anywhere with a one-liner:
@script.finance.convert(#amount, 'USD', 'CZK')
Quick start in 60 seconds
| Step | What you do | Where |
|---|---|---|
| 1 | Create a helper scriptCode = Finance.ConvertSource = #amount * 22.0 | Scripts register (Script reference) |
| 2 | Create a binding row with:fullName = finance.convertscript = Finance.Convert | Scripts / Bindings / Script Invocations |
| 3 | Call it from any other script:@script.finance.convert(100) | anywhere |
Result: the caller receives 2200.
Register-row schema (Scripts.Bindings.ScriptInvocations)
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
fullName | string | ✔ | – | The fully-qualified name you'll type after @script. |
script | string | ✔ | – | LOV to the target script code in the Scripts register. |
positionalArgs | boolean | – | false | Turn ON if the callee expects positional parameters (param1, param2, …). |
addCallerContext | boolean | – | true | Merge caller's #variables into the callee's context (caller wins on key clash). |
Call syntax
// named variables
@script.<package>.<code>({
key1: "value1",
key2: "value2",
})
// positional argumemts
@script.<package>.<code>( arg1, arg2, … )
- If
positionalArgs=false: Pass one map –@script.util.slugify({ "text" : #title }) - If
positionalArgs=true: Positional parameters land in the callee as#p0,#p1, … and an#argsarray.
Return value = whatever the callee script's last expression evaluates to.
Context variables inside the callee
| Variable | Available when | Contains |
|---|---|---|
#args | positionalArgs=true | full Object[] of arguments |
#p0, #p1, … | positionalArgs=true | individual positional parameters |
| (caller variables) | addCallerContext=true | every #variable the caller had, unless shadowed by an explicit argument key |
Example with named-argument map
Helper script – String.Pad
#text.padEnd(#width, #char ?: ' ')
Binding row
{
"fullName": "string.pad",
"script": "String.Pad",
"positionalArgs": false
}
Caller script
#padded = @script.string.pad({
"text" : #name,
"width" : 20,
"char" : '.'
})
#padded→"Invoice………………"
Error handling
| Exception | Thrown when | Typical fix |
|---|---|---|
ApiConfigurationException | no binding row matches fullName | Add or correct the row in Script Invocations. |
ApiValidationException | argument style mismatch (too many positional params, wrong type) | Pass a single map or set positionalArgs=true. |
Performance notes
- Bindings are cached for 5 minutes. Binding edits become visible after the cache expires.
- The callee runs in the same transaction / thread as the caller (no extra overhead).
Since the callee shares the caller's transaction, any entity changes made by the callee are committed or rolled back together with the caller. For more on transaction boundaries, see SpEL and Transactions.
Using paramsFormCode and resultFormCode
When a target script defines paramsFormCode and/or resultFormCode, those tSM Forms act as a typed contract for the binding:
| Script field | Effect on script-to-script binding |
|---|---|
paramsFormCode | The JSON Schema embedded in the form validates the parameter map at call time. Callers get autocomplete and inline documentation in the SpEL Console. |
resultFormCode | Documents the return structure so callers know what to expect. Currently informational — no runtime enforcement. |
Because a tSM Form is simultaneously a JSON Schema (data model) and a UI definition, a single artefact covers three concerns at once:
- Validation — parameters are checked against the schema before execution; type mismatches surface immediately.
- Documentation — field labels, descriptions, and constraints serve as living API docs for anyone calling the script.
- UI — the SpEL Console (and BPMN modeler) renders the form so users can fill in parameters interactively instead of writing raw JSON.
Always define paramsFormCode on scripts that are bound as reusable helpers. It makes the binding self-documenting and prevents callers from passing invalid data.
See also
- Script (reference) — script definition, types, parameter forms, and attributes.
- SpEL Console — developing and debugging SpEL scripts interactively.
- Event Bindings — trigger scripts on entity lifecycle events.
- REST Bindings — expose scripts as HTTP endpoints.
- MCP Bindings — expose scripts as AI-callable tools.
- SpEL and Transactions — how transactions affect SpEL scripts.
- Script Binding in BPMN — calling scripts from BPMN processes.