Skip to content

DMN and FEEL

TinyConductor evaluates DMN decisions and FEEL expressions inside the engine. DMN (Decision Model and Notation) is the standard for decision tables. FEEL is its expression language, which BPMN models also use.

Evaluation is deterministic. The same expression, the same variables and the same point in time always give the same result. This is what lets the engine replay a process’s history exactly.

  • Decision tables: all hit policies, and decision requirement (DRD) evaluation — a decision may require other decisions and business knowledge models.
  • Literal expressions: supported.
  • Business knowledge models: supported, including invocation from decisions. A business knowledge model whose logic is a decision table is not supported.
  • Decision services: single-output decision services can be invoked by id or name. Multi-output decision services, and calling a decision service from FEEL, are not supported.
  • Business rule tasks (tc:calledDecision) evaluate the deployed decision in the engine; no worker is involved. Deploy the DMN resource before the BPMN that calls it. The decision-evaluation record lists every evaluated decision, including required ones, with its evaluated inputs and matched rules.
  • Past evaluations of business rule tasks and of the evaluation API are searchable (POST /v2/decision-instances/search, by decision, process instance, state and evaluation time) and readable one by one with their inputs and matched rules (GET /v2/decision-instances/{key}), in the console under Decisions, Evaluations. They age out with the tenant’s history: a business rule task’s with its process instance, an API evaluation once it is older than the tenant’s history retention.
  • Deployed decisions and requirements graphs are searchable (POST /v2/decision-definitions/search and POST /v2/decision-requirements/search, by id, name, version and key) and readable by key, with the DMN file each was deployed from (GET /v2/decision-requirements/{key} and …/{key}/xml; one decision’s file with GET /v2/decision-definitions/{key}/xml), in the console under Decisions, Decisions and Requirements graphs. A user whose read access names only some decisions sees a requirements graph only when every decision of it is among them.

The sample order-decisions.dmn (see Examples) is a FIRST-hit decision table that requires a business knowledge model.

TinyConductor is tested against the public DMN Technology Compatibility Kit (TCK), the standard DMN test suite, at compliance level 3. The TCK has 3,369 assertions in 118 test files.

Every release must reach at least 3,133 passed, 6 failed, 230 unsupported. That is 99.81% of the supported features and 92.99% overall. The most recent run, which does not block releases, measured 3,137 passed, 12 failed and 220 unsupported.

  • The 6 failures are XML Schema extended years (up to ±999,999,999), which exceed the date range of the engine’s value model (±262,143 years).
  • The unsupported assertions are features outside the supported subset: external Java functions, DMN imports, multiple iteration contexts, decision tables as business-knowledge-model logic, some boxed invocation and relation shapes, FEEL comments, and XPath regular-expression constructs.

The FEEL implementation covers decimal, boolean and string expressions; lists, contexts and ranges; path, filter and index navigation; if, for and quantified expressions; unary tests; temporal values; and the standard list, string, numeric and context functions.

The following compatibility helper functions are available: is defined, nested get value, context put, context merge, extract, trim, to base64, is blank, duplicate values, is empty, partition, from json and to json. Only these names are provided; alternative spellings of them are not.

Also available:

FunctionNotes
number(from, grouping separator) and number(from, grouping separator, decimal separator)Parse numbers with explicit separators
fromAi(value, …) (one to five arguments)Returns its first argument unchanged. The description, type, schema and options arguments are metadata for the consuming integration; they are type-checked and must be literals
date and time with an offset plus an agreeing time zoneFor example +02:00[Europe/Berlin]

is defined with zero arguments is an error.

Every evaluation of an expression has a budget, so that one expression can neither slow down nor stop the engine for other processes and tenants:

  • Work: 100,000 evaluation steps. A tenant’s feelBudget quota changes this number (see Tenant quotas).
  • Memory: 4 MiB for everything the expression builds. The text a function returns counts (for example the result of replace, string join, split or extract), and so do lists built by for, by a list literal or by list functions such as concatenate and union, the entries of a context, joined strings and the variables a function definition keeps. A result that would not fit is refused before it is built.
  • Nesting: an expression may be nested at most 128 levels deep: brackets, operators, function calls, paths, if, for and the other constructs, counted together. A deeper expression is refused when the model is deployed. While an expression runs, its nesting and the functions it calls, including a function calling itself, may reach 256 levels.

An expression that goes over its budget fails like any other failing expression: the element raises an incident whose message starts with “FEEL evaluation exceeded”, and the rest of the engine carries on.

In a decision model, a decision or business knowledge model may require other ones in a chain at most 64 long; a longer chain fails the evaluation with an incident.

uuid() is not provided. When the engine replays history, it evaluates each expression again and must get the same value. A random result would break that. uuid() can only be added once the engine stores the random value in the history.

FEEL appears wherever a BPMN attribute starts with =: input and output mappings, conditions, timer definitions, correlation keys, job types and retries, called process ids, and multi-instance collections. Task headers are the exception: they are passed to workers exactly as written, including a leading =. Element-by-element support is listed in BPMN coverage.