Skip to main content

Overview

The Message Builder policy supports both single-line JEXL expressions and multi-line JEXL scripts. Script mode is activated when the template expression contains var, for, while, or if/else constructs.

Key Differences

FeatureJEXL ExpressionJEXL Script
Single-line evaluation
Multi-line code
for loop
var declaration
if/else block
return statement

Example 1: Converting a Tag Array to a JSON Array

Input Body

{
  "tags": [
    { "id": 1, "name": "outdoor" },
    { "id": 2, "name": "premium" },
    { "id": 3, "name": "sale" }
  ]
}

Template (JEXL Script)

#{
  var result = '[';
  var first = true;
  for (tag : body.$.tags) {
    if (!first) { result = result + ','; }
    result = result + '"' + tag.name + '"';
    first = false;
  }
  result + ']'
}
Body variables extracted via JSONPath are automatically converted to Java List or Map objects, so they support .size() and index access.

Expected Output

["outdoor","premium","sale"]

Example 2: Summing Order Items

Input Body

{
  "items": [
    { "name": "Book", "price": 29.99, "quantity": 2 },
    { "name": "Pen", "price": 4.50, "quantity": 5 },
    { "name": "Notebook", "price": 12.00, "quantity": 3 }
  ]
}

Template (JEXL Script)

#{
  var total = 0;
  for (item : body.$.items) {
    total = total + (item.price * item.quantity);
  }
  total
}

Expected Output

118.48

Example 3: Conditional Array Filtering

Filter array elements that meet a specific condition and build a new array.

Input Body

{
  "products": [
    { "name": "Laptop", "stock": 0 },
    { "name": "Phone", "stock": 15 },
    { "name": "Tablet", "stock": 0 },
    { "name": "Monitor", "stock": 8 }
  ]
}

Template (JEXL Script)

#{
  var result = '[';
  var first = true;
  for (p : body.$.products) {
    if (p.stock > 0) {
      if (!first) { result = result + ','; }
      result = result + '"' + p.name + '"';
      first = false;
    }
  }
  result + ']'
}

Expected Output

["Phone","Monitor"]

Example 4: Role-Based Authorization with if/else

Assign an authorization level based on user roles.

Setup

Assume a custom variable userRoles is already populated (e.g., from the request body) with value ["admin","editor"].

Template (JEXL Script)

#{
  var roles = userRoles;
  var level = 'NONE';
  for (var role : roles) {
    if (role == 'admin') {
      level = 'FULL';
    } else if (role == 'editor' && level != 'FULL') {
      level = 'WRITE';
    } else if (role == 'viewer' && level == 'NONE') {
      level = 'READ';
    }
  }
  level
}

Result

RolesauthLevel Value
["admin"]FULL
["editor","viewer"]WRITE
["viewer"]READ
[]NONE

Example 5: Accessing Array Elements with $[n] Syntax

To access a specific element of a root-level array, use $[n] syntax.

Input Body (Root Array)

[
  { "id": 1, "name": "First" },
  { "id": 2, "name": "Second" }
]

Variable Reference in Template

#{body.$[0].name}

Output

First
$[0] refers to the first element of the root array. $[1].id would return the id of the second element.

Tips and Common Mistakes

Use the standard body.$.path syntax directly inside the JEXL script. For example, for (tag : body.$.tags) iterates over the tags array. JSON array and object values are automatically converted to Java List and Map objects, enabling iteration and property access.
Yes, in JEXL Script mode you can use return value explicitly. However, returning a value from the last expression (as in examples above) is the recommended approach.
Yes. The Message Builder uses a balanced brace scanner to correctly identify #{} blocks, including those with nested curly braces such as JSON object literals.
Yes, JEXL Script supports while loops as well:
#{
  var list = body.$.items;
  var i = 0;
  var sum = 0;
  while (i < list.size()) {
    sum = sum + list[i].value;
    i = i + 1;
  }
  sum
}