From 94a506cbfc21d58c997931951444dd7771b8aad5 Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Wed, 15 Jul 2026 10:29:43 +0200 Subject: [PATCH] fix(workflow): read task query variables from 'variables', not 'processVariables' (refs #13) Flowable's POST query/tasks returns the included process variables under the key 'variables' (the request opts in via includeProcessVariables). The client DTO, its unit test, and the live-check parser all looked for 'processVariables', so the werkbak never matched a task's registrationId and verify-domain timed out. Verified by driving a real Flowable instance end-to-end locally: start -> complete external job -> the Beoordelen task carries registrationId under 'variables'. Co-Authored-By: Claude Opus 4.8 (1M context) --- infra/run-domain-check.sh | 3 ++- .../domain/Big.Infrastructure/FlowableWorkflowClient.cs | 6 ++++-- services/domain/Big.Tests/FlowableWorkflowClientTests.cs | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/infra/run-domain-check.sh b/infra/run-domain-check.sh index 7b3ce31..a701b21 100755 --- a/infra/run-domain-check.sh +++ b/infra/run-domain-check.sh @@ -87,8 +87,9 @@ try: except Exception: d={} rid=os.environ['REG_ID'] +# Flowable's task-query returns the included process variables under 'variables'. print(next((t['id'] for t in (d.get('data') or []) - if any(v.get('name')=='registrationId' and v.get('value')==rid for v in (t.get('processVariables') or []))), ''))"; } + if any(v.get('name')=='registrationId' and v.get('value')==rid for v in (t.get('variables') or []))), ''))"; } flcurl() { docker run --rm --network "$net" curlimages/curl:latest -fsS -u rest-admin:test "$@"; } query='{"processDefinitionKey":"registratie","taskDefinitionKey":"Beoordelen","includeProcessVariables":true}' diff --git a/services/domain/Big.Infrastructure/FlowableWorkflowClient.cs b/services/domain/Big.Infrastructure/FlowableWorkflowClient.cs index 597a6e6..f782cea 100644 --- a/services/domain/Big.Infrastructure/FlowableWorkflowClient.cs +++ b/services/domain/Big.Infrastructure/FlowableWorkflowClient.cs @@ -137,11 +137,13 @@ public sealed class FlowableWorkflowClient(HttpClient http, FlowableOptions opti private sealed record UserTaskDto( [property: JsonPropertyName("id")] string Id, - [property: JsonPropertyName("processVariables")] IReadOnlyList? ProcessVariables) + // Flowable's task-query returns the (included) process variables under "variables", not + // "processVariables"; the request opts in via includeProcessVariables. + [property: JsonPropertyName("variables")] IReadOnlyList? Variables) { /// The registration id this task carries as a process variable. public string RegistrationId() => - ProcessVariables?.SingleOrDefault(v => v.Name == "registrationId")?.Value + Variables?.SingleOrDefault(v => v.Name == "registrationId")?.Value ?? throw new InvalidOperationException($"Beoordelen task {Id} carries no registrationId variable."); } diff --git a/services/domain/Big.Tests/FlowableWorkflowClientTests.cs b/services/domain/Big.Tests/FlowableWorkflowClientTests.cs index 3262506..f1bf579 100644 --- a/services/domain/Big.Tests/FlowableWorkflowClientTests.cs +++ b/services/domain/Big.Tests/FlowableWorkflowClientTests.cs @@ -158,7 +158,7 @@ public class FlowableWorkflowClientTests var capture = new RequestCapture(); var client = Client(capture.Responds(HttpStatusCode.OK, $$""" - {"data":[{"id":"task-1","processVariables":[{"name":"registrationId","type":"string","value":"{{rid}}"}]}],"total":1} + {"data":[{"id":"task-1","variables":[{"name":"registrationId","type":"string","value":"{{rid}}"}]}],"total":1} """)); var tasks = await client.GetOpenBeoordelingenAsync(); @@ -192,7 +192,7 @@ public class FlowableWorkflowClientTests { var capture = new RequestCapture(); var client = Client(capture.Responds(HttpStatusCode.OK, - """{"data":[{"id":"task-1","processVariables":[]}],"total":1}""")); + """{"data":[{"id":"task-1","variables":[]}],"total":1}""")); var ex = await Assert.ThrowsAsync(() => client.GetOpenBeoordelingenAsync()); Assert.Contains("task-1", ex.Message);