DMN Workflow¶
This guide walks through uploading, deploying, testing, and exporting a DMN decision model as part of a service definition.
Prerequisites¶
- A
.dmnfile (DMN 1.3 XML format) - The service metadata tabs (Service, Organisation, Legal) filled in — the service identifier is used to construct DMN URIs
- Access to the Operaton rule engine (default:
https://operaton.open-regels.nl)
Step 1: Upload the DMN file¶
In the DMN tab, click Upload DMN File and select your .dmn file.
On upload, the editor:
- Parses all
<decision>elements from the XML - Filters out constant parameters (
p_*prefix) automatically - Extracts the primary decision key (the main output decision)
- Auto-generates a test request body from the
<inputData>elements - Shows a badge: "N testable decisions detected (p_* constants filtered)"
If you do not have a DMN file yet, click Load Example to use the provided AOW example.
Step 2: Review the syntactic validation result¶
Immediately after upload, the editor runs the file through the five-layer syntactic validator and displays the result in the file card.
If the file is valid, a green Syntax valid badge appears. Any warnings or informational messages are shown in a collapsed panel — review them before deploying.
If the file has errors, the panel expands automatically and lists the issues grouped by layer. Address the errors in your DMN authoring tool before proceeding with deployment.
| Badge | Meaning |
|---|---|
| 🟢 Syntax valid | No errors. Warnings and info messages may still be present. |
| 🔴 Validation failed | One or more errors detected. Deployment will likely fail or produce incorrect results. |
Tip
Warnings in the Interaction Rules layer often indicate orphaned <inputData> elements — inputs that exist in the DRD but are not connected to any decision via <informationRequirement>. These are harmless for execution but result in dead data in the model.
For a full explanation of every issue code and its rationale, see the DMN Validation Reference.
Step 3: Configure the API endpoint¶
The Base URL identifies the Operaton engine to deploy to and evaluate against. It defaults to https://operaton.open-regels.nl — change it if you are using a different instance.
The Evaluation URL preview below it shows the URL the editor will actually call. Since v2026.08.0 that is a Linked Data Explorer backend endpoint, not an Operaton one: the browser posts to the backend, and the backend calls Operaton server-to-server. Calling the engine directly from the browser is blocked by CORS, so this indirection is what makes deploy and evaluate work in local development.
Pointing local development at a local engine
Set REACT_APP_OPERATON_URL in your .env to target a local Operaton container. Without it the Base URL falls back to the shared production instance — so a local dev session would otherwise deploy to, and evaluate against, shared infrastructure.
Step 4: Deploy to Operaton¶
Click Deploy to Operaton. The editor posts the DMN file to the backend's POST /v1/dmns/deploy, which forwards it to the engine.
On success, the button changes to Deployed — ID: {deployment-id} and the deployment ID and timestamp are stored. These are included in the Turtle output.
Step 5: Test the decision¶
Review the auto-generated request body in the test panel. Edit variable values to match your test scenario.
Click Evaluate Decision. The editor calls POST /v1/dmns/evaluate/{decisionKey} on the backend, which evaluates the decision on Operaton and returns the result. The response is displayed inline.
If the file contains more than one testable decision, use the Decision Key dropdown on the DMN File card to choose which decision to evaluate — the editor defaults to the root decision (one no other decision requires), but you can point it at any of them, and the evaluation URL updates to match (v1.10.3).
For multi-table DMNs, expand the Intermediate Decision Tests section and click Run Intermediate Tests to evaluate each sub-decision individually — useful for isolating which part of a complex DRD is producing an unexpected result. For batch, verified scenario testing, see DMN Testing.
Step 6: Export TTL with DMN metadata¶
Click Download TTL. The exported file includes:
- The
cprmv:DecisionModelentity with deployment ID (cprmv:deploymentId) and API endpoint (cprmv:implementedBy) - All input variables as
cpsv:Inputentities and output variables ascpsv:Outputentities - All extracted decision rules as
cpsv:Rule, cprmv:DecisionRuleentities (withdct:title/dct:description), each linked to the relevant legal article viacprmv:isBasedOnand, when a legal resource is set, to theeli:LegalResourceviacpsv:implements
The DMN section is appended after the core service metadata.
Tips¶
- Fill in the Service identifier before uploading the DMN — it is used to construct the DMN model URI.
- Use descriptive decision keys in your DMN XML (e.g.
zorgtoeslag_resultaatrather thanDecision_1). - Do not use spaces in decision keys — use underscores or camelCase.
- Deploy and test before exporting. Undeployed DMN metadata in the Turtle output has no deployment ID, which limits its usefulness.
- Resolve all validation errors before deploying. Warnings are advisory and will not prevent a successful deployment.
Authoring pitfalls¶
Bringing a real, tool-exported DMN (Amsterdam's 25-decision HvA model) to a deployable and evaluable state surfaced a set of defects that a syntactically valid file can still carry. They are worth checking in any DMN produced by an authoring tool rather than hand-written.
Blocking deployment:
| Symptom | Cause | Fix |
|---|---|---|
| Deployment rejected | No camunda:historyTimeToLive on the decisions |
Set it on every <decision> |
| Deployment rejected, XML parse error | Unescaped & in knowledgeSource URLs |
Escape as & |
Blocking evaluation — the file deploys, but decisions cannot be evaluated:
| Symptom | Cause | Fix |
|---|---|---|
FEEL/SCALA-01008 |
Multi-word bare names in input expressions — the FEEL engine consumes only the first word | Flatten names to a single token |
| Blank, unlogged exception | <dmn:output> declares label but no name; Operaton needs name to serialise the result |
Add name to every <dmn:output> |
DMN-01005 Invalid value … for clause with type 'date' |
A date input sent as a string | Send the full ISO timestamp with type: "Date" — the editor now does this automatically |
Silently wrong results — evaluation succeeds but the logic is not what was intended:
not -andnot(null) -are malformed FEEL:notrequires a parenthesised argument. Rewrite asfalseandnot(null)respectively, after confirming the intent against the business rule.- Bare
and-joined comparisons are not valid unary tests. Rewrite in interval notation, e.g.[18..67). not "met partner"needs parentheses:not("met partner").- A decision with a wildcard default rule must not use
hitPolicy="UNIQUE"(the implicit default) — the default rule always matches alongside a specific one. UseFIRST.