Введение и основы JEXL#
Введение в языки выражений#
Языки выражений — специализированные языки для вычисления выражений во время работы программы. Они позволяют динамически выполнять математические, логические и строковые операции, обращаться к свойствам объектов и вызывать методы без компиляции кода.
Языки выражений работают в работающей программе, позволяя гибко менять логику — например, проверять условия user.age > 18 или вычислять формулы price * quantity без перезапуска приложения.
Зачем они нужны:
Гибкость — изменение логики без перекомпиляции приложения;
Безопасность — ограниченный набор операций снижает риски выполнения вредоносного кода;
Удобство — простой синтаксис для нетривиальных вычислений;
Динамическая оценка — выражения могут загружаться из внешних источников.
JEXL — библиотека, реализующая язык выражений для вычисления и выполнения скриптов в Java-приложениях.
Редактор JEXL#
Путь доступа:
Откройте главное меню системы.
Перейдите в раздел Сервисы.
Выберите подраздел Инструменты.
Нажмите пункт Выполнить JEXL-скрипт.
При открытии редактора отображается рабочее пространство с тремя функциональными областями:

Панель инструментов — набор кнопок для управления скриптами:
Выполнить — запуск текущего скрипта.
Сохранить.
Откатить.
Обновить.
Открыть скрипт из библиотеки JEXL — выбор скрипта из общего/личного хранилища.
Информация + Аудит JEXL — просмотр метаданных и истории изменений
.Проверить правильность JEXL скрипта — проверка синтаксиса написанного кода.
Помощь — краткая справка по существующим методам.
Помощь — вкладка с методами и их кратким описанием;
Список объектов — список объектов API всей системы;
Контекст — фильтр отображения методов по контексту, API, математическим функциям;
К оглавлению — возврат к редактору кода;
Обновить;
Проверить правильность Jexl скрипта;
Официальная документация.
Выход.
Рабочая область — написание и редактирование JEXL-кода.
Журнал выполнения — хронология выполнения скриптов, ошибки и предупреждения, системные сообщения.
Очистить логи — удаление всей текущей истории сообщений из журнала.
Основы синтаксиса выражений#
Простые выражения#
JEXL поддерживает стандартные операторы, аналогичные Java:
Арифметика:
var sum = 5 + 3; // 8
var total = 8 * 10; // 80
var remainder = 10 % 3; // 1
Логические операции:
var isActive = true;
var isEligible = (age >= 18) && isActive;
var isAdmin = (role == "admin") || (role == "superuser");
Сравнения:
price == 100
name != 'admin'
score > 90
Поддерживаемые типы данных#
JEXL работает с основными типами:
числа — целые (42), дробные (3.14);
строки — в одинарных („text“), двойных («text») или обратных кавычках (
test);булевы значения — true, false;
null — отсутствие значения;
коллекции — списки [1, 2, 3], мапы {„key“: „value“}, множества {1, 2, 3}.
Обертки для безопасной передачи данных#
В JEXL для работы со Scala-методами, требующими строгой типизации и поддержки null, используются специальные обертки.
Scala — статически типизированный язык, где:
null для примитивов (Long, Int) запрещен.
При вызове Scala-методов из JEXL:
JEXL передает «сырые» значения (String, Number, null);
Scala ожидает строгие типы (NLong, NGid).
Null-типы и их назначения:
Null-тип |
Назначение |
|---|---|
NLong |
Работа с идентификаторами (ID) |
NNumber |
Работа с целыми/дробными числами |
NGid |
Работа с глобальными идентификаторами (GUID) |
NDate |
Работа с датами |
NString |
Работа со строками (с поддержкой null) |
NBigDecimal |
Точные расчеты (деньги, финансы) |
NDuration |
Арифметика временных промежутков |
Создание Null-типа на примере NLong:
var NLong = function(number) {
return new ("ru.bitec.app.gtk.lang.NLong", number);
};
var nlValue = NLong(21l);
Конкретное применение null-типов:
// Создаем Map с параметрами для заказа
Map1.put(
new ("ru.bitec.app.gtk.lang.NLong", ropStageDet.id),
new ("ru.bitec.app.gtk.lang.NNumber", ropStageDet.nQty)
);
// Создаем заказ
idvOrder = Stm_OrderOutApi.createOrderByContractStage(
ropStage.id,
idvDepOwner,
idvOrderType,
asScala(Map1), // Основные параметры
asScala(EmptyMap), // Доп. параметры 1
asScala(EmptyMap), // Доп. параметры 2
null
);
Работа с переменными#
Способы объявления переменных#
JEXL предоставляет три способа объявления переменных: let, const и var, каждый с своей областью видимости и правилами изменяемости.
let — Локальная переменная
Ключевое слово let создаёт переменную, доступную только внутри блока { }, где она объявлена, включая вложенные блоки. Переменная не может быть переопределена в той же области.
Пример:
if (56 < 100) {
let sText = "Example text";
}
dialogs.showMessage(sText) // ошибка: переменная объявлена в другом блоке
const — Неизменяемая переменная
Переменная, объявленная через const, имеет блочную область видимости, но её значение нельзя изменить после инициализации.
Пример:
if (56 < 100) {
const sText = "Example text";
sText = "Changed text"; // Ошибка: изменение константы
}
Исключение: если const ссылается на объект, его внутренние свойства могут изменяться — неизменной остаётся только ссылка.
Пример:
const arrayEven = [2, 4, 6, 8];
arrayEven[0] = 10;
dialogs.showMessage(arrayEven[0]); // Вывод: 10
var — Глобальная переменная
По умолчанию var создаёт переменную, видимую во всём скрипте, и позволяет её переопределять:
if (56 < 100) {
var sText = "Example text";
sText = "Changed text";
}
sText = "Outer text"; // Изменение разрешено
dialogs.showMessage(sText); // Вывод: Outer text
Когда что использовать:
const — для значений, которые не должны меняться;
let — для обычных переменных внутри блоков;
var — для глобальных переменных (с осторожностью).
Объявления переменных поддерживаемых типов#
Числовые типы:
var nValue = 42; // Целое число
var fValue = 42.0f; // Число с плавающей точкой
var lValue = 42L; // Длинное целое
var dValue = 42.0d; // Число двойной точности
var bigIntValue = 42H; // Большое целое
var bigDecValue = 42.0B; // Число высокой точности
var hexValue = 0x2A; // Шестнадцатеричное число
var octValue = 052; // Восьмеричное число
var sciValue = 4.2E+1D; // Число в научной нотации
Строковые типы:
var sStr1 = "Hello"; // Строка (двойные кавычки)
var sStr2 = 'World'; // Строка (одинарные кавычки)
var sStr3 = `line1 // Многострочный комментарий
line2
line3
`;
var intValue = 10
var interpolatedStr = `Value: ${intValue}`; // Строка с подстановкой
var regex = ~/pattern\d+/; // Регулярное выражение
Специальные значения:
var bVal = true; // Логическое значение
var nVal = null; // Пустое значение
var tuple2 = (v1, v2) -> { return new(`scala.Tuple2`, v1, v2); }; // Кортеж
Коллекции:
var array = [1, 2, 3]; // Массив
var objArray = [1, "two", 3.0]; // Массив объектов
var list = [1, 2, 3, ...]; // Список
var set = {"a", "b", "c"}; // Множество
var map = {"key1": 1, "key2": 2}; // Карта
var range = 1..10; // Диапазон чисел
var rop = Stm_OrderOutApi.load(id); // Строка роп соответствующая объекту БД
Пустые коллекции:
var emptyArray = []; // Пустой массив
var emptyList = [...]; // Пустой список
var emptySet = {}; // Пустое множество
var emptyMap = {:}; // Пустая карта
Доступ к свойствам объектов#
Два варианта доступа к объекту:
// Через точку (автоматически вызывает getter)
var sClientName = order.client.name;
// Через метод
var nTotal = order.getTotal();