Camunda DMN 决策引擎实战:独立运行与 BPMN 业务规则任务集成指南

Camunda DMN 决策引擎实战:独立运行与 BPMN 业务规则任务集成指南 Camunda DMN 决策引擎实战独立运行与 BPMN 业务规则任务集成指南【免费下载链接】camunda-bpm-platformCamunda 7 CE is End of Life (EoL). Please check out Camunda 8 instead (https://github.com/camunda/camunda) or read about Camunda 7 Enterprise End of Life (https://camunda.com/blog/2025/02/camunda-7-enterprise-end-of-life-extension/) – Camunda 7 CE was a flexible framework for workflow and decision automation using BPMN and DMN.项目地址: https://gitcode.com/GitHub_Trending/ca/camunda-bpm-platformcamunda-engine-dmn是 Camunda 7 平台中基于 Java 编写的轻量级 DMNDecision Model and Notation决策执行引擎能够解析 DMN 决策模型并求值决策。本文将围绕 engine-dmn/README.md 的核心内容展开先讲解如何以独立Standalone方式把引擎引入 Maven 工程并用纯 Java API 解析、求值决策再演示如何让 BPMN 流程中的业务规则任务Business Rule Task通过camunda:decisionRef无缝引用 DMN 决策将决策逻辑编排进工作流。读完本文你将掌握 DMN 引擎的最小可运行工程搭建、决策表求值结果 API、底层求值与命中策略实现以及它与 Camunda 流程引擎的完整集成链路。一、模块定位可独立运行、也可与 BPMN/CMMN 组合使用根据 engine-dmn/README.md 的定位说明该决策引擎以 Java 实现核心价值在于轻量Lightweight Execution Engine for DMN并且既可以与 BPMN、CMMN 无缝组合使用也可以完全独立运行。从仓库结构看engine-dmn模块是一个由多个子模块组成的多模块工程engine-dmn/engine引擎主体提供DmnEngine接口、默认实现与全部内部机制engine-dmn/feel-apiFEEL 表达式的 SPI 接口FeelEngine、FeelEngineFactoryengine-dmn/feel-juel将 FEEL 语法翻译为 JUEL 求值的兼容实现engine-dmn/feel-scala对 Scala FEEL Engine 的集成实现参见 feel-scala/README.md是现代版本默认使用的 FEEL 引擎。从 engine-dmn/engine/pom.xml 的依赖声明可以印证引擎的组成它依赖camunda-dmn-modelDMN 模型 API、camunda-engine-feel-api、camunda-engine-feel-juel、camunda-engine-feel-scala、feel-enginescala-shaded以及camunda-juel表达式语言求值、camunda-commons-typed-values类型化变量与camunda-commons-utils。这意味着一个引擎实例内部实际串联起了 DMN 模型解析、表达式求值与类型化变量三大能力。二、独立使用三分钟跑通一个 DMN 引擎2.1 引入 Maven 坐标独立使用方式下只需在项目中加入如下依赖原文档示例groupId 为org.camunda.bpm.dmndependency groupIdorg.camunda.bpm.dmn/groupId artifactIdcamunda-engine-dmn/artifactId version${version.camunda}/version /dependency${version.camunda}需要替换为具体的版本号。需要说明的是当前仓库的engine-dmn/engine/pom.xml中版本为7.24.0-SNAPSHOT且注明7.24.0 是 Camunda 7 社区版在 Maven Central 发布的最后一个版本后续该构件不会再发布新版本企业版提供扩展维护使用时应留意这一版本前提。2.2 编写第一个求值程序原文档给出了一个完整的独立使用示例核心步骤分为构建引擎 → 解析决策 → 准备输入数据 → 求值决策表四步public class DmnApp { public static void main(String[] args) { // configure and build the DMN engine DmnEngine dmnEngine DmnEngineConfiguration.createDefaultDmnEngineConfiguration().buildEngine(); // parse a decision DmnDecision decision dmnEngine.parseDecision(orderDecision, CheckOrder.dmn); MapString, Object data new HashMapString, Object(); data.put(status, gold); data.put(sum, 354.12d); // evaluate a decision DmnDecisionTableResult result dmnEngine.evaluateDecisionTable(decision, data); } }各步骤的关键点如下构建引擎DmnEngineConfiguration.createDefaultDmnEngineConfiguration().buildEngine()。从源码看DmnEngineConfiguration.java 是抽象类createDefaultDmnEngineConfiguration()返回默认实现DefaultDmnEngineConfigurationbuildEngine()在 DefaultDmnEngineConfiguration.java 中会先调用init()依次初始化指标收集器、决策表求值监听器、决策求值监听器、脚本引擎解析器、表达式语言默认值、EL Provider 与 FEEL 引擎随后返回new DefaultDmnEngine(this)。解析决策parseDecision(orderDecision, CheckOrder.dmn)。其中orderDecision是 DMN 文件中dmn:decision元素的id属性即决策 key第二个参数可以是InputStream或DmnModelInstance。DmnEngine.java 中定义了完整的 API 面除parseDecision外还提供parseDecisions(...)解析文件中的全部决策parseDecisionRequirementsGraph(...)解析决策需求图DRGevaluateDecisionTable(...)以决策表结果形式求值evaluateDecision(...)求值任意支持的决策逻辑决策表、字面量表达式等返回更通用的DmnDecisionResult。 若给定的 key 找不到对应决策DefaultDmnEngine.java 会抛出unableToFindDecisionWithKey异常。准备输入数据普通MapString, Object即可引擎内部会通过Variables.fromMap(variables).asVariableContext()将其转换为类型化的VariableContext供表达式求值使用。求值决策表evaluateDecisionTable返回DmnDecisionTableResult。注意该方法要求目标决策必须实现为决策表decision table否则抛出decisionIsNotADecisionTable异常。2.3 读取求值结果DmnDecisionTableResult APIevaluateDecisionTable的返回值是DmnDecisionTableResult本质是ListDmnDecisionRuleResult。DmnDecisionTableResult.java 定义了以下便捷方法方法语义getFirstResult()返回第一条命中的决策规则结果无命中则返回 nullgetSingleResult()返回唯一命中结果若命中多于一条则抛出DmnEngineExceptioncollectEntries(outputName)按输出名收集所有命中规则在该输出列上的值getResultList()返回所有命中规则的输出名→值映射列表getSingleEntry()断言仅一条命中且仅一个输出返回该输出值getSingleEntryTyped()同getSingleEntry()但返回类型化值TypedValue在唯一命中 单输出的典型场景例如 UNIQUE 命中策略的审批人决策中一行result.getSingleEntry()即可取回最终决策值。三、决策表求值原理输入列逐列过滤、命中策略收敛为了让求值不只是黑盒调用这里结合源码补充其底层实现。DecisionTableEvaluationHandler.java 是决策表求值的核心处理器其evaluate流程为逐输入列求值对每个输入列先求值输入表达式Input Expression得到类型化输入值TypedValue并把当前输入值注入局部VariableContext可通过输入列的inputVariable在规则条件中引用逐列过滤规则从全部规则开始用每一列的输入项Input Entry即条件表达式对候选规则做过滤只有条件求值为true的规则进入下一轮最终得到全部匹配规则Matching Rules求值输出对匹配规则逐列求值输出项Output Entry并将原始值按输出列的类型定义Type Definition转换为类型化值可参考type包下的StringDataTypeTransformer、IntegerDataTypeTransformer、BooleanDataTypeTransformer、DateDataTypeTransformer、DoubleDataTypeTransformer、LongDataTypeTransformer等内置类型转换器应用命中策略调用决策表配置的HitPolicyHandler收敛匹配规则见下文通知监听器向所有注册的决策表求值监听器广播DmnDecisionTableEvaluationEvent。其中输入项条件若为 FEEL 表达式会走evaluateFeelSimpleUnaryTests即用 FEEL 引擎的evaluateSimpleUnaryTests求值简单一元测试simple unary tests空白输入项恒视为true。3.1 命中策略Hit Policy全景命中策略决定多条规则命中时如何处理输出。DefaultHitPolicyHandlerRegistry.java 中的默认注册表完整覆盖了 DMN 规范定义的策略Hit Policy聚合器行为UNIQUE无恰好命中一条规则否则异常FIRST无返回命中顺序中第一条规则输出ANY无多条命中时要求所有输出一致否则抛DmnHitPolicyExceptionRULE ORDER无返回所有命中规则的输出保持规则顺序COLLECT无返回所有命中规则的输出COLLECTCOUNT返回命中规则数量COLLECTSUM返回命中规则输出的总和COLLECTMIN返回命中规则输出的最小值COLLECTMAX返回命中规则输出的最大值以 ANY 为例AnyHitPolicyHandler.java 在apply中会比较所有匹配规则的输出映射若全部相等则只保留第一条并返回若存在不等则抛出anyHitPolicyRequiresThatAllOutputsAreEqual异常。该注册表支持通过addHandler扩展自定义命中策略处理器SPI 位于impl.spi.hitpolicy。四、表达式语言与引擎配置4.1 默认表达式语言DMN 引擎支持 FEEL 与 JUEL 两类表达式。DefaultDmnEngineConfiguration.java 定义了四类表达式语言默认值defaultInputExpressionExpressionLanguage输入表达式defaultInputEntryExpressionLanguage输入项条件defaultOutputEntryExpressionLanguage输出项结论defaultLiteralExpressionLanguage字面量表达式。在不开启 FEEL 遗留行为时四者默认均为 FEEL若设置enableFeelLegacyBehavior(true)则输入表达式与输出项回退为 JUEL仅输入项保持 FEEL。注意表达式若在 DMN 文件中显式声明了expressionLanguage将优先使用显式声明配置值仅作用于未声明的表达式。4.2 引擎默认依赖链从 engine-dmn/engine/pom.xml 可以看到 FEEL 支持的完整依赖链默认使用feel-enginescala-shaded与camunda-engine-feel-scala而camunda-engine-feel-juel则作为 FEEL 遗留行为的实现对应 DefaultDmnEngineConfiguration.java 中enableFeelLegacyBehavior为 true 时使用FeelEngineFactoryImpl否则使用ScalaFeelEngineFactory的逻辑。camunda-juel为 JUEL 表达式提供底层 EL 求值能力。4.3 常用可配置项DmnEngineConfiguration及默认实现DefaultDmnEngineConfiguration还支持以下常用扩展点指标收集器engineMetricCollector(...)默认实现为DefaultEngineMetricCollector内部以AtomicLong统计累计执行的决策实例数executed decision instances与决策元素数executed decision elements并提供clearExecutedDecisionInstances()/clearExecutedDecisionElements()清零方法见 DefaultEngineMetricCollector.java求值监听器customPreDecisionTableEvaluationListeners(...)/customPostDecisionTableEvaluationListeners(...)以及决策级customPreDecisionEvaluationListeners(...)/customPostDecisionEvaluationListeners(...)可用于审计、日志或指标采集脚本引擎解析器scriptEngineResolver(...)用于解析表达式语言对应的脚本引擎EL ProviderelProvider(...)默认JuelElProviderFEEL 自定义函数feelCustomFunctionProviders(...)向 Scala FEEL 引擎注册自定义函数转换器transformer(...)默认DefaultDmnTransformer负责把 DMN 模型实例转换为引擎内部结构空白输出处理setReturnBlankTableOutputAsNull(true)时空白输出项也作为null写入结果默认策略是丢弃空白输出项。该选项有专门的测试类 ReturnBlankTableOutputAsNullTest.java 覆盖。配置接口的完整方法清单参见 DmnEngineConfiguration.java引擎的解析/求值 API 参见 DmnEngine.java。五、在 BPMN 流程中实现业务规则任务独立运行之外更常见的生产场景是把 DMN 决策嵌入 BPMN 流程。原文档的第二部分给出了完整方案。5.1 依赖与准备在流程引擎应用中需要引入流程引擎本体与内存数据库示例中 H2 仅用于测试作用域dependency groupIdorg.camunda.bpm/groupId artifactIdcamunda-engine/artifactId version${version.camunda}/version /dependency dependency groupIdcom.h2database/groupId artifactIdh2/artifactId version1.3.168/version scopetest/scope /dependency5.2 在 BPMN 中引用 DMN 决策在 BPMN 流程文件里声明一个业务规则任务Business Rule Task并通过 Camunda 扩展属性camunda:decisionRef指向 DMN 决策bpmn:businessRuleTask idassignApprover camunda:decisionRefinvoice-assign-approver camunda:resultVariableapproverGroups nameAssign Approver Group(s) /bpmn:businessRuleTaskcamunda:decisionRef必填值为 DMN 文件中决策的id注意是id而非name即invoice-assign-approvercamunda:resultVariable可选指定将决策结果保存到流程变量名示例中为approverGroups不声明时结果默认写入流程变量decisionResult。对应的 DMN 文件片段dmn:decision idinvoice-assign-approver nameAssign Approver ... /dmn:decision从流程引擎的解析源码看camunda:decisionRef的处理位于 BpmnParse.java解析器读取CAMUNDA_BPMN_EXTENSIONS_NS命名空间下的decisionRef属性并将其包装为参数值提供者ParameterValueProvider同时支持以下配套绑定属性camunda:decisionRefBinding绑定方式latest/deployment/version/versionTagcamunda:decisionRefVersion结合version绑定指定决策版本camunda:decisionRefVersionTag结合versionTag绑定指定版本标签camunda:decisionRefTenantId指定多租户场景下的租户。5.3 部署并启动流程最后把 BPMN 文件与 DMN 文件作为一个 Deployment 一起部署再按流程 key 启动流程实例public class App { public static void main(String[] args) { ProcessEngine processEngine ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration() .buildProcessEngine(); try { processEngine.getRepositoryService() .createDeployment() .name(invoice deployment) .addClasspathResource(invoice.bpmn) .addClasspathResource(assign-approver-groups.dmn) .deploy(); processEngine.getRuntimeService() .startProcessInstanceByKey(invoice, createVariables() .putValue(invoceNumber, 2323)); } finally { processEngine.close(); } } }要点说明createStandaloneInMemProcessEngineConfiguration()创建基于内存数据库的独立流程引擎适合测试与演示addClasspathResource同时注册 BPMN 与 DMN 资源流程引擎会在部署阶段解析 DMN 文件并建立decisionRef与决策 id 的映射startProcessInstanceByKey(invoice, ...)中的invoice是 BPMN 流程的id启动后流程流转至业务规则任务时会自动执行对应的 DMN 决策并把结果写入resultVariable指定的流程变量finally中的processEngine.close()用于释放引擎资源。5.4 组合使用时的求值结果形态需要留意的是当 DMN 决策被流程引擎调用时引擎内部同样走DmnEngine的求值链路决策表求值 → 命中策略收敛 → 监听器通知最终结果以DmnDecisionTableResult形式映射为流程变量。因此第四节中关于命中策略与输出行为的说明同样适用于 BPMN 集成场景。六、版本说明与注意事项当前仓库engine-dmn/engine的版本为7.24.0-SNAPSHOT根据 engine-dmn/engine/pom.xml 的说明7.24.0 是 Camunda 7 社区版在 Maven Central 的最后一个发布版本之后社区版不再发布新版本如需要扩展维护请关注企业版方案在实际项目中应把${version.camunda}替换为可用的正式版本号。camunda:decisionRef引用的是 DMN 决策的id属性拼写错误或文件中不存在该 id 时求值/解析阶段会抛出异常unableToFindDecisionWithKey。evaluateDecisionTable只适用于决策表类型的决策若决策以字面量表达式literal expression等其他决策逻辑实现应使用evaluateDecision通用求值 API见 DmnEngine.java。七、延伸阅读引擎完整 APIDmnEngine.java配置与构建DmnEngineConfiguration.java、DefaultDmnEngineConfiguration.java决策表求值实现DecisionTableEvaluationHandler.java命中策略注册表DefaultHitPolicyHandlerRegistry.java求值结果 APIDmnDecisionTableResult.java引擎功能测试示例DmnEngineApiTest.java、EvaluateDecisionTest.java、HitPolicyTest.javaBPMNdecisionRef解析逻辑BpmnParse.java【免费下载链接】camunda-bpm-platformCamunda 7 CE is End of Life (EoL). Please check out Camunda 8 instead (https://github.com/camunda/camunda) or read about Camunda 7 Enterprise End of Life (https://camunda.com/blog/2025/02/camunda-7-enterprise-end-of-life-extension/) – Camunda 7 CE was a flexible framework for workflow and decision automation using BPMN and DMN.项目地址: https://gitcode.com/GitHub_Trending/ca/camunda-bpm-platform创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考