Saltar a contenido

Dmn Integration

Zeebe integra un engine DMN basado en dmn-scala para evaluar decisiones de negocio directamente dentro del workflow engine, sin necesidad de un servicio externo. La evaluación usa FEEL (Friendly Enough Expression Language) como lenguaje de expresiones. El bridge entre BPMN y DMN es BpmnDecisionBehavior, invocado por el BusinessRuleTaskProcessor cuando el elemento tiene un calledDecisionId.

Arquitectura del DMN engine

El engine DMN vive en el módulo zeebe/dmn/ y actúa como wrapper sobre la biblioteca dmn-scala:

zeebe/dmn/
├── DmnScalaDecisionEngine      ← Wrapper principal
├── ParsedDmnScalaDrg            ← Resultado del parsing
├── FeelToMessagePackTransformer ← Conversión FEEL result → MessagePack
└── ... (support classes)

DmnScalaDecisionEngine

Clase principal que expone dos operaciones fundamentales:

parse(InputStream dmnResource) → ParsedDmnScalaDrg

Parsea un archivo DMN XML y produce un ParsedDmnScalaDrg (Decision Requirements Graph parseado). El parsing: 1. Lee el XML DMN 1.3 usando el parser de dmn-scala. 2. Valida la estructura (decision tables, input/output expressions, hit policies). 3. Pre-compila las expresiones FEEL de cada celda de la decision table. 4. Retorna un objeto inmutable listo para evaluación repetida.

El parsing ocurre una sola vez durante el deployment del recurso DMN. El ParsedDmnScalaDrg se almacena en el state store y se reutiliza para todas las evaluaciones.

evaluateDecisionById(ParsedDmnScalaDrg drg, String decisionId, Map<String, Object> variables) → DecisionEvaluationResult

Evalúa una decisión específica dentro del DRG: 1. Busca la decisión por decisionId dentro del DRG parseado. 2. Si la decisión depende de otras decisiones (DRG con dependencias), las evalúa recursivamente en orden topológico. 3. Para cada decision table: evalúa las input expressions contra las variables provistas, matchea las reglas, aplica la hit policy. 4. Retorna el resultado con todas las decisiones evaluadas en la cadena.

FEEL (Friendly Enough Expression Language)

El lenguaje de expresiones usado tanto en DMN como en los mappings y condiciones BPMN. Zeebe usa la implementación feel-scala que soporta FEEL 1.4+:

Características clave de FEEL: - Tipado: number, string, boolean, date, time, duration, list, context, null. - Expresiones: literales, aritmética, comparación, lógica, rangos ([1..10]), filtros (list[item > 5]). - Funciones built-in: string manipulation, date/time, list operations, numeric functions. - Contextos: {name: "foo", age: 30} — equivalente a objetos/maps. - Invocación de funciones con named parameters.

En el contexto DMN: las input expressions, input entries, y output entries de una decision table son expresiones FEEL. El engine evalúa cada una contra las variables de input.

En el contexto BPMN: las condiciones de sequence flows, input/output mappings, y timer expressions también son FEEL.

Bridge BPMN-DMN: BpmnDecisionBehavior

BpmnDecisionBehavior es el behavior que conecta la ejecución BPMN con el engine DMN:

Flujo de evaluateDecision(context, element)

  1. Resolver decision ID: extrae el calledDecisionId del elemento BPMN (configurado en el XML del proceso).
  2. Resolver binding: según el binding type, determina qué versión de la decisión DMN usar:
  3. latest: la última versión deployada de la decisión.
  4. deployment: la versión que fue deployada junto con el proceso BPMN en el mismo deployment. Garantiza consistencia: el proceso siempre usa la decisión con la que fue deployado.
  5. versionTag: una versión específica identificada por tag semántico.
  6. Obtener el DRG parseado: busca el ParsedDmnScalaDrg en el state store por (decisionId, version).
  7. Recopilar variables: obtiene las variables del scope actual del element instance para usarlas como input de la decisión.
  8. Evaluar: invoca DmnScalaDecisionEngine.evaluateDecisionById() con el DRG, el decision ID, y las variables.
  9. Convertir resultado: usa FeelToMessagePackTransformer para convertir el resultado FEEL a formato MessagePack (el formato binario de variables de Zeebe).
  10. Escribir variables de resultado: el output de la decisión se escribe como variables en el scope del element instance.
  11. Emitir evento: escribe un record DecisionEvaluationIntent.EVALUATED o DecisionEvaluationIntent.FAILED con metadata completa de la evaluación.

FeelToMessagePackTransformer

Convierte tipos FEEL a MessagePack (el formato de serialización de variables de Zeebe):

Tipo FEEL Tipo MessagePack
number Double o Long
string String
boolean Boolean
date String (ISO 8601)
time String (ISO 8601)
duration String (ISO 8601)
list Array
context Map
null Nil

La conversión es necesaria porque dmn-scala usa tipos Java nativos, mientras que Zeebe almacena variables en MessagePack para eficiencia de espacio y velocidad de serialización/deserialización.

Binding types en detalle

latest (default)

  • Usa la última versión deployada de la decisión DMN al momento de la evaluación.
  • Riesgo: si se deploya una nueva versión de la decisión mientras una instancia de proceso está corriendo, instancias distintas del mismo proceso pueden evaluar versiones distintas de la decisión.
  • Caso de uso: decisiones que deben actualizarse en caliente sin re-deployar el proceso.

deployment

  • Usa la versión de la decisión DMN que fue deployada en el mismo DeployResource call que el proceso BPMN.
  • Garantía: todas las instancias de una versión del proceso siempre evalúan la misma versión de la decisión.
  • Restricción: la decisión DMN y el proceso BPMN deben deployarse juntos en la misma request.
  • Caso de uso: consistencia estricta entre lógica de proceso y reglas de negocio.

versionTag

  • Usa la versión de la decisión DMN identificada por un tag semántico (e.g., "v2.1").
  • Flexibilidad: permite referenciar versiones específicas sin acoplarse al deployment.
  • Caso de uso: procesos que necesitan pinear una versión específica de las reglas.

Evento DecisionEvaluation

Cada evaluación de decisión DMN genera un record en el log stream:

DecisionEvaluationIntent.EVALUATED

Indica una evaluación exitosa. Incluye: - decisionKey, decisionId, decisionName, decisionVersion. - decisionRequirementsId, decisionRequirementsKey (el DRG al que pertenece). - output: resultado de la decisión. - evaluatedDecisions: lista de todas las decisiones evaluadas en la cadena (si el DRG tiene dependencias). Cada una con sus input/output y reglas matcheadas. - processInstanceKey, elementId: contexto BPMN donde se evaluó.

DecisionEvaluationIntent.FAILED

Indica un fallo en la evaluación. Incluye: - Misma metadata que EVALUATED. - failedDecisionId: qué decisión específica falló (puede ser una dependencia). - failureMessage: descripción del error (input faltante, tipo inválido, expresión FEEL inválida, etc.).

Cuando la evaluación falla, BpmnDecisionBehavior crea un incidente en el element instance via BpmnIncidentBehavior, bloqueando la instancia hasta que un operador resuelva el problema (corrigiendo variables o re-deployando la decisión).