fix(workflow): use a DMN service task, not businessRuleTask (S-13, refs #14)
Some checks failed
CI / lint (pull_request) Successful in 1m15s
CI / build (pull_request) Successful in 58s
CI / unit (pull_request) Successful in 1m9s
CI / frontend (pull_request) Successful in 2m28s
CI / mutation (pull_request) Successful in 5m19s
CI / verify-stack (pull_request) Failing after 7m53s

flowable-rest's businessRuleTask parse handler binds the legacy Drools/KIE
implementation (NoClassDefFoundError: org.kie.api...AgendaFilter at deploy time),
so registratie.bpmn failed to deploy and flowable-init exited 22. Flowable's
supported inline-DMN construct is a serviceTask with flowable:type="dmn" — switch
to it. The DMN cross-deploy via the process repository (previous commit) was fine;
this was the BPMN parse. Docs/comments updated to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-18 11:15:46 +02:00
parent 2411e72aee
commit 60ea61f0ed
7 changed files with 25 additions and 21 deletions

View File

@@ -1,4 +1,4 @@
# ADR-0016: Diploma eligibility is a DMN evaluated inline as a BPMN businessRuleTask # ADR-0016: Diploma eligibility is a DMN evaluated inline as a BPMN DMN service task
- **Status:** Accepted - **Status:** Accepted
- **Date:** 2026-07-17 - **Date:** 2026-07-17
@@ -22,14 +22,16 @@ back. That is one option; it is not the only one, and it is not the cleanest.
## Decision ## Decision
**The diploma-eligibility DMN is deployed to Flowable and evaluated inline by the registratie process **The diploma-eligibility DMN is deployed to Flowable and evaluated inline by the registratie process
as a `businessRuleTask`; an exclusive gateway routes on its output. The domain's only new job is to as a DMN service task (`flowable:type="dmn"`); an exclusive gateway routes on its output. The domain's
carry the diploma origin and pass it into the process as a start variable.** only new job is to carry the diploma origin and pass it into the process as a start variable.**
- **The decision lives in the workflow.** `workflows/diploma-eligibility.dmn` maps `diplomaOrigin` - **The decision lives in the workflow.** `workflows/diploma-eligibility.dmn` maps `diplomaOrigin`
`route` (`Buitenlands``CBGV_ADVIES`, otherwise `DIRECT`). A `businessRuleTask` `route` (`Buitenlands``CBGV_ADVIES`, otherwise `DIRECT`). A DMN service task
(`flowable:type="dmn"`, `decisionTableReferenceKey=diploma-eligibility`) runs it between (`flowable:type="dmn"`, `decisionTableReferenceKey=diploma-eligibility`) runs it between
`OpenZaakAanmaken` and `Beoordelen`, and an exclusive gateway sends `CBGV_ADVIES` through a new `OpenZaakAanmaken` and `Beoordelen`, and an exclusive gateway sends `CBGV_ADVIES` through a new
`CBGVAdvies` user task before `Beoordelen`, `DIRECT` straight there. `CBGVAdvies` user task before `Beoordelen`, `DIRECT` straight there. (A `businessRuleTask` would
bind Flowable's legacy Drools/KIE implementation, which `flowable-rest` does not bundle — its parse
handler throws `NoClassDefFoundError` at deploy time; the DMN service task is the supported route.)
- **The domain carries the input, not the decision.** The `Registration` aggregate gains a - **The domain carries the input, not the decision.** The `Registration` aggregate gains a
`DiplomaOrigin` (Binnenlands/Buitenlands); `SubmitRegistration` passes it to `DiplomaOrigin` (Binnenlands/Buitenlands); `SubmitRegistration` passes it to
`StartRegistrationProcessAsync`, which sets it as the `diplomaOrigin` start variable. The domain `StartRegistrationProcessAsync`, which sets it as the `diplomaOrigin` start variable. The domain
@@ -52,7 +54,7 @@ carry the diploma origin and pass it into the process as a start variable.**
- Deviates from #14's literal "evaluated by the Domain Service via Workflow Client" wording (noted on - Deviates from #14's literal "evaluated by the Domain Service via Workflow Client" wording (noted on
the issue). The outcome — DMN decides eligibility, foreign diplomas get the CBGV step — is unchanged. the issue). The outcome — DMN decides eligibility, foreign diplomas get the CBGV step — is unchanged.
- The DMN and its `businessRuleTask` wiring are validated live (verify-domain drives a foreign - The DMN and its service-task wiring are validated live (verify-domain drives a foreign
registration through CBGV-advies and a domestic one straight to beoordeling, exercising both registration through CBGV-advies and a domestic one straight to beoordeling, exercising both
branches), not in unit tests — consistent with ADR-0009/0014/0015. The domain unit/acceptance tests branches), not in unit tests — consistent with ADR-0009/0014/0015. The domain unit/acceptance tests
cover only that the origin is carried into the process. cover only that the origin is carried into the process.

View File

@@ -346,7 +346,7 @@ candidate group behandelaar → teamlead (§8.2).
## S-13 — Diploma-eligibility: foreign diplomas route through CBGV-advies (#14, ADR-0016) ## S-13 — Diploma-eligibility: foreign diplomas route through CBGV-advies (#14, ADR-0016)
A registration's diploma origin decides its route. A DMN `businessRuleTask` in the registratie A registration's diploma origin decides its route. A DMN service task in the registratie
process evaluates the `diploma-eligibility` decision on the `diplomaOrigin` start variable: a process evaluates the `diploma-eligibility` decision on the `diplomaOrigin` start variable: a
**foreign** (Buitenlands) diploma is routed through an extra **CBGV-advies** user task before **foreign** (Buitenlands) diploma is routed through an extra **CBGV-advies** user task before
beoordeling; a **domestic** (Binnenlands) one goes straight to beoordeling. The decision lives in the beoordeling; a **domestic** (Binnenlands) one goes straight to beoordeling. The decision lives in the
@@ -376,7 +376,7 @@ curl -s -u rest-admin:test -X POST "$FL/runtime/tasks/$TID" \
``` ```
**The path:** domain sets the `diplomaOrigin` start variable → registratie process DMN **The path:** domain sets the `diplomaOrigin` start variable → registratie process DMN
`businessRuleTask` sets `route` → exclusive gateway → foreign: `CBGVAdvies` user task → `Beoordelen`; DMN service task sets `route` → exclusive gateway → foreign: `CBGVAdvies` user task → `Beoordelen`;
domestic: `Beoordelen` directly (§8.2, ADR-0016). domestic: `Beoordelen` directly (§8.2, ADR-0016).
> The domestic/foreign paths are covered by the `Een diploma op herkomst routeren` acceptance > The domestic/foreign paths are covered by the `Een diploma op herkomst routeren` acceptance

View File

@@ -270,7 +270,7 @@ services:
until curl -sf -u rest-admin:test "$$base" >/dev/null 2>&1; do echo "waiting for flowable-rest..."; sleep 3; done until curl -sf -u rest-admin:test "$$base" >/dev/null 2>&1; do echo "waiting for flowable-rest..."; sleep 3; done
# Deploy the diploma-eligibility DMN via the process repository: the flowable-rest image embeds # Deploy the diploma-eligibility DMN via the process repository: the flowable-rest image embeds
# the DMN engine but does not expose the dmn-api app, so the process deployment cross-deploys the # the DMN engine but does not expose the dmn-api app, so the process deployment cross-deploys the
# .dmn resource to the DMN engine, where the registratie businessRuleTask resolves it by key # .dmn resource to the DMN engine, where the registratie DMN service task resolves it by key
# (S-13, ADR-0016). # (S-13, ADR-0016).
if curl -s -u rest-admin:test "$$base?name=diploma-eligibility" | grep -q '"name":"diploma-eligibility"'; then if curl -s -u rest-admin:test "$$base?name=diploma-eligibility" | grep -q '"name":"diploma-eligibility"'; then
echo "diploma-eligibility already deployed; skip" echo "diploma-eligibility already deployed; skip"

View File

@@ -51,7 +51,7 @@ services:
until curl -sf -u rest-admin:test "$$base" >/dev/null 2>&1; do echo "waiting for flowable-rest..."; sleep 3; done until curl -sf -u rest-admin:test "$$base" >/dev/null 2>&1; do echo "waiting for flowable-rest..."; sleep 3; done
# Deploy the diploma-eligibility DMN via the process repository: the flowable-rest image embeds # Deploy the diploma-eligibility DMN via the process repository: the flowable-rest image embeds
# the DMN engine but does not expose the dmn-api app, so the process deployment cross-deploys the # the DMN engine but does not expose the dmn-api app, so the process deployment cross-deploys the
# .dmn resource to the DMN engine, where the registratie businessRuleTask resolves it by key # .dmn resource to the DMN engine, where the registratie DMN service task resolves it by key
# (S-13, ADR-0016). # (S-13, ADR-0016).
if curl -s -u rest-admin:test "$$base?name=diploma-eligibility" | grep -q '"name":"diploma-eligibility"'; then if curl -s -u rest-admin:test "$$base?name=diploma-eligibility" | grep -q '"name":"diploma-eligibility"'; then
echo "diploma-eligibility already deployed; skip" echo "diploma-eligibility already deployed; skip"

View File

@@ -159,7 +159,7 @@ done
echo "OK — withdrawal cancelled the Beoordelen task; the registratie process ended (ingetrokken)" echo "OK — withdrawal cancelled the Beoordelen task; the registratie process ended (ingetrokken)"
# ── S-13: diploma-eligibility routing. A registration with a FOREIGN diploma must route through the # ── S-13: diploma-eligibility routing. A registration with a FOREIGN diploma must route through the
# extra CBGVAdvies user task before Beoordelen (the DMN businessRuleTask sets route=CBGV_ADVIES and the # extra CBGVAdvies user task before Beoordelen (the DMN service task sets route=CBGV_ADVIES and the
# gateway branches, ADR-0016). The domestic DIRECT path is already proven by the first registration # gateway branches, ADR-0016). The domestic DIRECT path is already proven by the first registration
# above, which parked straight at Beoordelen. ────────────────────────────────────────────────────── # above, which parked straight at Beoordelen. ──────────────────────────────────────────────────────
cbgv_query='{"processDefinitionKey":"registratie","taskDefinitionKey":"CBGVAdvies","includeProcessVariables":true}' cbgv_query='{"processDefinitionKey":"registratie","taskDefinitionKey":"CBGVAdvies","includeProcessVariables":true}'

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Diploma-eligibility decision (S-13, ADR-0016). Evaluated inline by the registratie process as a <!-- Diploma-eligibility decision (S-13, ADR-0016). Evaluated inline by the registratie process as a
BPMN businessRuleTask: given the diploma's origin, it sets the `route` the process should take. BPMN DMN service task: given the diploma's origin, it sets the `route` the process should take.
A foreign (Buitenlands) diploma routes through the extra CBGV-advies assessment step; a domestic A foreign (Buitenlands) diploma routes through the extra CBGV-advies assessment step; a domestic
one (or anything else) goes DIRECT to beoordeling. FIRST hit policy: the foreign rule wins, and one (or anything else) goes DIRECT to beoordeling. FIRST hit policy: the foreign rule wins, and
the empty-input catch-all is the default. --> the empty-input catch-all is the default. -->

View File

@@ -22,9 +22,9 @@
(BeoordelingEscaleren); the Workflow Client reassigns the still-open Beoordelen task from the (BeoordelingEscaleren); the Workflow Client reassigns the still-open Beoordelen task from the
behandelaar group to teamlead (ADR-0015). The Beoordelen task stays open throughout — the timer behandelaar group to teamlead (ADR-0015). The Beoordelen task stays open throughout — the timer
only changes who may claim it. only changes who may claim it.
S-13 adds diploma-eligibility routing: between OpenZaakAanmaken and Beoordelen a DMN S-13 adds diploma-eligibility routing: between OpenZaakAanmaken and Beoordelen a DMN service
businessRuleTask evaluates the `diploma-eligibility` decision on the diplomaOrigin start task (flowable:type="dmn") evaluates the `diploma-eligibility` decision on the diplomaOrigin
variable; an exclusive gateway routes a foreign diploma through the CBGV-advies user task start variable; an exclusive gateway routes a foreign diploma through the CBGV-advies user task
before Beoordelen, a domestic one straight there (ADR-0016). --> before Beoordelen, a domestic one straight there (ADR-0016). -->
<message id="Message_Ingetrokken" name="RegistratieIngetrokken"/> <message id="Message_Ingetrokken" name="RegistratieIngetrokken"/>
@@ -40,17 +40,19 @@
<sequenceFlow id="flow2" sourceRef="OpenZaakAanmaken" targetRef="DiplomaEligibiliteit"/> <sequenceFlow id="flow2" sourceRef="OpenZaakAanmaken" targetRef="DiplomaEligibiliteit"/>
<!-- S-13: evaluate the diploma-eligibility DMN inline (ADR-0016). Flowable runs the deployed <!-- S-13: evaluate the diploma-eligibility DMN inline (ADR-0016). A Flowable DMN service task
`diploma-eligibility` decision against the diplomaOrigin start variable and sets the `route` (flowable:type="dmn" — NOT a businessRuleTask, whose default implementation is the legacy
output as a process variable. The gateway then routes a foreign diploma through CBGV-advies, Drools/KIE one that flowable-rest does not bundle) runs the deployed `diploma-eligibility`
a domestic one straight to Beoordelen. --> decision against the diplomaOrigin start variable and sets the `route` output as a process
<businessRuleTask id="DiplomaEligibiliteit" name="Diploma-eligibiliteit bepalen" flowable:type="dmn"> variable. The gateway then routes a foreign diploma through CBGV-advies, a domestic one
straight to Beoordelen. -->
<serviceTask id="DiplomaEligibiliteit" name="Diploma-eligibiliteit bepalen" flowable:type="dmn">
<extensionElements> <extensionElements>
<flowable:field name="decisionTableReferenceKey"> <flowable:field name="decisionTableReferenceKey">
<flowable:string><![CDATA[diploma-eligibility]]></flowable:string> <flowable:string><![CDATA[diploma-eligibility]]></flowable:string>
</flowable:field> </flowable:field>
</extensionElements> </extensionElements>
</businessRuleTask> </serviceTask>
<sequenceFlow id="flow2a" sourceRef="DiplomaEligibiliteit" targetRef="RouteOpDiploma"/> <sequenceFlow id="flow2a" sourceRef="DiplomaEligibiliteit" targetRef="RouteOpDiploma"/>