From c9acf7c4a52f8f5ba3456cf574e0c18c88f99467 Mon Sep 17 00:00:00 2001 From: Francisco Javier Tirado Sarti Date: Mon, 30 Sep 2024 18:20:04 +0200 Subject: [PATCH] [Fix #3674] Signalling compensation when abortion --- .../instance/impl/ProcessInstanceImpl.java | 9 +++ .../java/org/jbpm/ruleflow/core/Metadata.java | 1 + .../parser/ServerlessWorkflowParser.java | 1 + .../src/main/resources/compensation.sw.json | 4 +- .../resources/compensation_aborted.sw.json | 59 +++++++++++++++++++ .../quarkus/workflows/CompensationRestIT.java | 20 ++++++- 6 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/compensation_aborted.sw.json diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/ProcessInstanceImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/ProcessInstanceImpl.java index 98ea0bbee86..b685860357e 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/ProcessInstanceImpl.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/ProcessInstanceImpl.java @@ -27,11 +27,13 @@ import org.drools.core.common.InternalKnowledgeRuntime; import org.jbpm.process.core.Context; import org.jbpm.process.core.ContextContainer; +import org.jbpm.process.core.context.exception.CompensationScope; import org.jbpm.process.core.impl.XmlProcessDumper; import org.jbpm.process.core.impl.XmlProcessDumperFactory; import org.jbpm.process.instance.ContextInstance; import org.jbpm.process.instance.InternalProcessRuntime; import org.jbpm.process.instance.ProcessInstance; +import org.jbpm.ruleflow.core.Metadata; import org.jbpm.workflow.core.WorkflowProcess; import org.kie.api.definition.process.Process; import org.kie.api.runtime.rule.Agenda; @@ -152,9 +154,16 @@ public void setState(final int state, String outcome) { } public void internalSetState(final int state) { + if (state == KogitoProcessInstance.STATE_ABORTED && automaticCompensation()) { + signalEvent(Metadata.COMPENSATION, CompensationScope.IMPLICIT_COMPENSATION_PREFIX + process.getId()); + } this.state = state; } + private boolean automaticCompensation() { + return process.getMetaData().containsKey(Metadata.COMPENSATE_WHEN_ABORTED); + } + @Override public int getState() { return this.state; diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/Metadata.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/Metadata.java index 6bca5445bf4..b552fd128b6 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/Metadata.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/Metadata.java @@ -62,6 +62,7 @@ public class Metadata { public static final String LINK_NAME = "LinkName"; public static final String CONDITION = "Condition"; public static final String IS_FOR_COMPENSATION = "isForCompensation"; + public static final String COMPENSATE_WHEN_ABORTED = "compensateIfAborted"; public static final String CORRELATION_KEY = "CorrelationKey"; public static final String CUSTOM_ASYNC = "customAsync"; public static final String CUSTOM_AUTO_START = "customAutoStart"; diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/ServerlessWorkflowParser.java b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/ServerlessWorkflowParser.java index b7ef57251f9..8fd92f82f35 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/ServerlessWorkflowParser.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/ServerlessWorkflowParser.java @@ -147,6 +147,7 @@ private GeneratedInfo parseProcess() { handlers.forEach(StateHandler::handleConnections); if (parserContext.isCompensation()) { factory.metaData(Metadata.COMPENSATION, true); + factory.metaData(Metadata.COMPENSATE_WHEN_ABORTED, true); factory.addCompensationContext(workflow.getId()); } TimeoutsDefinition timeouts = workflow.getTimeouts(); diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/compensation.sw.json b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/compensation.sw.json index 884b5fc16da..8c35b7c4fc6 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/compensation.sw.json +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/compensation.sw.json @@ -1,8 +1,8 @@ { "id": "compensation", "version": "1.0", - "name": "Workflow Error example", - "description": "An example of how compensation works", + "name": "Workflow compensation", + "description": "Test compensation works", "start": "printStatus", "errors": [ { diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/compensation_aborted.sw.json b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/compensation_aborted.sw.json new file mode 100644 index 00000000000..363513baf88 --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/compensation_aborted.sw.json @@ -0,0 +1,59 @@ +{ + "id": "automatic_compensation", + "version": "1.0", + "name": "Workflow abortion compensation", + "description": "Testing automatic compensation on abort", + "start": "double", + "functions": [ + { + "name": "double", + "type": "expression", + "operation": ".value*=2" + }, + { + "name": "half", + "type": "expression", + "operation": ".value/=2" + }], + "events": [ + { + "name": "never", + "source": "", + "type": "never" + } + ], + "states": [ + { + "name": "double", + "type": "operation", + "compensatedBy" : "half", + "actions" : [{ + "functionRef" : "double" + }], + "transition": "waitEvent" + }, + { + "name": "waitEvent", + "type": "event", + "onEvents": [ + { + "eventRefs": [ + "never" + ], + "actions": [ + ] + } + ], + "end" : true + }, + { + "name": "half", + "usedForCompensation" : true, + "type": "operation", + "actions" : [{ + "functionRef" : "half" + }], + "end": true + } + ] +} diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/CompensationRestIT.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/CompensationRestIT.java index 596f8e14b68..e6af51a69cf 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/CompensationRestIT.java +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/CompensationRestIT.java @@ -52,7 +52,6 @@ public void testErrorRest2() { .statusCode(201) .body("workflowdata.compensated", is(true)) .body("workflowdata.isEven", is(false)); - } @Test @@ -66,4 +65,23 @@ public void testErrorRest3() { .statusCode(201) .body("workflowdata.compensated", is(false)); } + + @Test + public void testCompensationOnAbort() { + String pid = given() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .body("{\"value\" : 2}").when() + .post("/automatic_compensation") + .then() + .statusCode(201).extract().path("id"); + given() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .when() + .delete("/automatic_compensation/" + pid) + .then() + .statusCode(200) + .body("workflowdata.value", is(2)); + } }