Skip to content
Stand with Ukraine flag

TBEL Language Guide

This guide covers the TBEL syntax, data types, collections, and control-flow constructs. For the full list of built-in utility functions, see the Helper Functions reference.

TBEL is based on MVEL. A few syntax rules differ from JavaScript:

  • Use foreach instead of for...of / for...in. Traditional for loops are also supported.
  • Ternary expressions must be wrapped in parentheses when used outside an explicit if statement.
  • Multiple statements require semicolons; the semicolon after the final statement is optional.

Access properties from context objects directly:

msg.temperature
return (msg.temperature > 10 && msg.temperature < 20) ||
(msg.humidity > 10 && msg.humidity < 60);

Standard operator precedence applies. Use parentheses to control execution order.

Statements are separated by semicolons. The value of the last statement is the script’s return value:

var a = 2;
var b = 3;
a + b; // returns 5

TBEL automatically converts compatible types:

"123" == 123; // true

Maps are created inline and use a custom implementation with built-in memory tracking.

var map = {"temperature": 42, "nested": "508"};
map.temperature // dot notation
map.get("temperature") // method call
map["temperature"] // bracket notation

Safe-navigation prevents NullPointerException on missing keys:

if (map.?nonExistingKey.smth > 10) { }

Explicit entrySet():

foreach (element : map.entrySet()) {
element.getKey(); // or element.key
element.getValue(); // or element.value
}

Implicit (iterates over values):

foreach (value : map) {
// process each value
}
map.temperature = 0; // set value
map.put("humidity", 73); // add entry
map.putIfAbsent("temperature1", 73); // add if missing
map.replace("temperature", 56); // replace value
map.replace("temperature", 56, 42); // conditional replace
map.remove("temperature"); // remove entry
var keys = map.keys(); // get all keys
var values = map.values(); // get all values
var size = map.size(); // entry count
var memorySize = map.memorySize(); // memory in bytes
map.sortByKey(); // sort by key in-place
var sorted = map.sortByValue(); // sort by value in-place
map.putAll({"test": 12, "input": {"http": 130}}); // merge another map
isMap(map); // type check → true
var original = {};
original.humidity = 73;
var unmodifiable = original.toUnmodifiable();
unmodifiable.put("temperature1", 96); // throws error: Map is unmodifiable

Lists use a custom implementation with memory tracking. Only inline creation is permitted.

var list = ["A", "B", "C"];
list[0]; // "A"
list.size(); // 3
foreach (item : list) {
var smth = item;
}
for (var i = 0; i < list.size; i++) {
var smth = list[i];
}
list.add(3, "thingsboard"); // insert at index
list.push("thingsboard"); // append to end
list.unshift("r"); // prepend to start
list.addAll(["thingsboard", 4, 67]); // append all elements
list.addAll(2, ["x", "y"]); // insert all at index
var removed = list.remove(2); // remove by index
list.remove("C"); // remove by value
var first = list.shift(); // remove and return first
var last = list.pop(); // remove and return last
var spliced = list.splice(3); // remove from index to end
list.splice(2, 2); // remove 2 elements at index 2
list.splice(1, 4, "start", 5, "end"); // remove 4, insert replacements
list.set(3, "65"); // replace at index
list[1] = "98"; // bracket assignment
list.sort(); // ascending sort (default)
list.sort(true); // ascending
list.sort(false); // descending
list.reverse(); // reverse in-place
list.fill(67); // fill entire list
list.fill(4, 1); // fill from index 1
list.fill(2, 1, 4); // fill range [1, 4)

These return a new list without modifying the original:

var sorted = list.toSorted(); // new sorted list (ascending)
var sortedDesc = list.toSorted(false); // new sorted list (descending)
var reversed = list.toReversed(); // new reversed list
var sliced = list.slice(0, 2); // new sublist [0, 2)
var replaced = list.with(1, 69); // new list with index 1 replaced
var merged = list.concat(otherList); // new concatenated list
var str = list.join(); // join elements into string
var spliced = list.toSpliced(1, 0, "Feb"); // new list with splice applied
var length = list.length();
var memorySize = list.memorySize();
var idx = list.indexOf("B", 1); // first index of "B" starting from 1
list.validateClazzInArrayIsOnlyNumber(); // validate numeric content
isList(list); // type check → true
var original = [];
original.add(0x67);
var unmodifiable = original.toUnmodifiable();
unmodifiable.add(0x35); // throws error: List is unmodifiable

Sets are ordered collections that prevent duplicates.

var set1 = toSet(["B", "A", "C", "A"]); // from list (3 elements — "A" deduplicated)
var set2 = createSet(); // empty set
var set3 = createSet(["A", "B", "C"]); // from list
var set4 = newSet(); // empty set
foreach (item : set) {
// process item
}
var arr = set.toArray();
for (var i = 0; i < set.size; i++) {
var item = arr[i];
}
set.add(35); // add single element (returns true if new)
set.addAll(otherSet); // merge another set
set.remove(4); // remove element
set.clear(); // remove all elements
set.contains("A"); // membership check → true/false
set.size(); // element count
set.toArray(); // convert to array
set.toList(); // convert to list
set.clone(); // shallow copy
isSet(set); // type check → true
set.sort(); // ascending in-place
set.sort(true); // ascending in-place
set.sort(false); // descending in-place
var sorted = set.toSorted(); // new sorted set (ascending)
var sortedDesc = set.toSorted(false); // new sorted set (descending)
var original = createSet();
original.add(0x67);
var unmodifiable = original.toUnmodifiable();
unmodifiable.add(0x35); // throws error: Set is unmodifiable

TBEL supports arrays only for primitive types. String indexing returns characters, and string arrays are automatically converted to lists.

var array = new int[3];
array[0] = 1;
array[1] = 2;
array[2] = 3;
var str = "My String";
var ch = str[0]; // 'M'
isArray(array); // true

Custom function example:

function sum(list) {
var result = 0;
for (var i = 0; i < list.length; i++) {
result += list[i];
}
return result;
}
var total = sum(array); // 6

Single or double quotes:

"This is a string literal"
'This is also string literal'

Escape sequences: \\, \n, \r, \u#### (Unicode), \### (octal).

125 // decimal integer
0353 // octal
0xAFF0 // hexadecimal
10.503 // double
94.92d // explicit double
14.5f // float
104.39484B // BigDecimal
8.4I // BigInteger
true
false
null
nil // alias for null

TBEL allows limited use of Java classes from java.util and java.lang:

var foo = Math.sqrt(4); // 2.0

Convert numbers to hex, octal, or binary using Integer.toString():

var b16 = Integer.toString(0x1A, 16); // "1a"
var b10 = Integer.toString(0x1A, 10); // "26"
var b8 = Integer.toString(0x1A, 8); // "32"
var b2 = Integer.toString(0x1A, 2); // "11010"

Negative numbers:

var i16 = Integer.toString(-255, 16); // "-ff"
var i10 = Integer.toString(-255, 10); // "-255"
var i8 = Integer.toString(-255, 8); // "-377"
var i2 = Integer.toString(-255, 2); // "-11111111"

Float and double hex strings:

var f0 = 7823764.8374;
var f16 = Float.toHexString(f0); // "0x1.dd8654p22"
var dd0 = 99993219.156013e-002;
var dd16 = Double.toHexString(dd0); // "0x1.e83f862142b5bp19"

Long conversion:

var l16 = Long.toString(9223372036854775807, 16); // "7fffffffffffffff"
var l10 = Long.toString(9223372036854775807, 10); // "9223372036854775807"
var l8 = Long.toString(9223372036854775807, 8); // "777777777777777777777"
var l2 = Long.toString(9223372036854775807, 2); // "111...111" (63 ones)

Creating new instances of Java classes is not allowed:

java.util.Collections.reverse(list); // allowed — static method call
list = new java.util.ArrayList(); // NOT allowed — constructor call
var metadataStr = JSON.stringify(metadata);
var metadata = JSON.parse(metadataStr);
if (temperature > 0) {
return "Greater than zero!";
} else if (temperature == -1) {
return "Minus one!";
} else {
return "Something else!";
}
temperature > 0 ? "Yes" : "No";
var numbers = [1, 2, 3];
var sum = 0;
foreach (n : numbers) {
sum += n;
}

Strings are iterable character-by-character:

foreach (c : "ABCDEFGHIJKLMNOPQRSTUVWXYZ") {
// process each character
}
var sum = 0;
for (var i = 0; i < 100; i++) {
sum += i;
}
while (isTrue()) {
doSomething();
}
until (isFalse()) {
doSomething();
}
do {
x = something();
} while (x != null);
do {
x = something();
} until (x == null);