What are the best practices for canceling a request and returning to the previous step?

Hi,

I have a BPMN model using Camunda 8 and Spring Boot, and I would like to accomplish two things.

First, I want to allow users to cancel the process at any time. To achieve this, I plan to use a parallel gateway, where one of the paths leads to a User Task. If this task is running, it should terminate the process flow.

Second, at one of the steps, I need to check if the time surpasses the current day, which would require returning to the previous step. For this, I am using a Time Boundary Event.

I have provided my Camunda BPMN code below. What are the best practices I should follow for these scenarios? Thank you!

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:zeebe="http://camunda.org/schema/zeebe/1.0" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_01a37ij" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.31.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.5.0">
  <bpmn:process id="civil_partnership_payment_order_process" name="buidDiscount" isExecutable="true">
    <bpmn:userTask id="create_payment_order_lnd" name="CREATE">
      <bpmn:extensionElements>
        <zeebe:formDefinition formKey="create_payment_order_lnd" />
      </bpmn:extensionElements>
      <bpmn:incoming>Flow_0r414ln</bpmn:incoming>
      <bpmn:incoming>Flow_17ccf9b</bpmn:incoming>
      <bpmn:incoming>Flow_0px6wn3</bpmn:incoming>
      <bpmn:outgoing>Flow_0rrh299</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:sequenceFlow id="Flow_0r414ln" sourceRef="StartEvent_1" targetRef="create_payment_order_lnd" />
    <bpmn:sequenceFlow id="Flow_0rrh299" sourceRef="create_payment_order_lnd" targetRef="Gateway_0gapglz" />
    <bpmn:parallelGateway id="Gateway_0gapglz">
      <bpmn:incoming>Flow_0rrh299</bpmn:incoming>
      <bpmn:outgoing>Flow_027jamc</bpmn:outgoing>
      <bpmn:outgoing>Flow_067wy8h</bpmn:outgoing>
    </bpmn:parallelGateway>
    <bpmn:sequenceFlow id="Flow_027jamc" sourceRef="Gateway_0gapglz" targetRef="Activity_1blhfrh" />
    <bpmn:sequenceFlow id="Flow_00rahlc" sourceRef="Activity_1blhfrh" targetRef="Event_0a4lqk7" />
    <bpmn:endEvent id="Event_0a4lqk7">
      <bpmn:incoming>Flow_00rahlc</bpmn:incoming>
      <bpmn:terminateEventDefinition id="TerminateEventDefinition_0iya0h5" />
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="Flow_067wy8h" sourceRef="Gateway_0gapglz" targetRef="lms_announcement_finalization_lnd" />
    <bpmn:exclusiveGateway id="Gateway_0m8tdol">
      <bpmn:incoming>Flow_0beouvl</bpmn:incoming>
      <bpmn:outgoing>Flow_17ccf9b</bpmn:outgoing>
      <bpmn:outgoing>Flow_01yqgzh</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:sequenceFlow id="Flow_0beouvl" sourceRef="lms_announcement_finalization_lnd" targetRef="Gateway_0m8tdol" />
    <bpmn:sequenceFlow id="Flow_17ccf9b" sourceRef="Gateway_0m8tdol" targetRef="create_payment_order_lnd">
      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=lmsAnnouncementFinalizationRevoke=true</bpmn:conditionExpression>
    </bpmn:sequenceFlow>
    <bpmn:sequenceFlow id="Flow_01yqgzh" sourceRef="Gateway_0m8tdol" targetRef="Activity_04wv1js">
      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=lmsAnnouncementFinalizationRevoke=false</bpmn:conditionExpression>
    </bpmn:sequenceFlow>
    <bpmn:receiveTask id="Activity_04wv1js" name="In Progress" messageRef="Message_34h9gfv">
      <bpmn:incoming>Flow_01yqgzh</bpmn:incoming>
      <bpmn:incoming>Flow_19qo79v</bpmn:incoming>
      <bpmn:outgoing>Flow_0ffz97k</bpmn:outgoing>
    </bpmn:receiveTask>
    <bpmn:exclusiveGateway id="Gateway_0lim3al" default="Flow_0mkqmtb">
      <bpmn:incoming>Flow_0ffz97k</bpmn:incoming>
      <bpmn:outgoing>Flow_19qo79v</bpmn:outgoing>
      <bpmn:outgoing>Flow_0mkqmtb</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:sequenceFlow id="Flow_0ffz97k" sourceRef="Activity_04wv1js" targetRef="Gateway_0lim3al" />
    <bpmn:sequenceFlow id="Flow_19qo79v" sourceRef="Gateway_0lim3al" targetRef="Activity_04wv1js" />
    <bpmn:sequenceFlow id="Flow_0mkqmtb" sourceRef="Gateway_0lim3al" targetRef="Event_0dwy0xh" />
    <bpmn:endEvent id="Event_0dwy0xh">
      <bpmn:incoming>Flow_0mkqmtb</bpmn:incoming>
      <bpmn:terminateEventDefinition id="TerminateEventDefinition_1xdvq3f" />
    </bpmn:endEvent>
    <bpmn:startEvent id="StartEvent_1">
      <bpmn:outgoing>Flow_0r414ln</bpmn:outgoing>
      <bpmn:messageEventDefinition id="MessageEventDefinition_098bxwq" />
    </bpmn:startEvent>
    <bpmn:userTask id="lms_announcement_finalization_lnd" name="FINALIZE">
      <bpmn:extensionElements>
        <zeebe:formDefinition formKey="lms_announcement_finalization_lnd" />
      </bpmn:extensionElements>
      <bpmn:incoming>Flow_067wy8h</bpmn:incoming>
      <bpmn:outgoing>Flow_0beouvl</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:sequenceFlow id="Flow_0px6wn3" sourceRef="Event_1xregc1" targetRef="create_payment_order_lnd" />
    <bpmn:boundaryEvent id="Event_1xregc1" attachedToRef="Activity_04wv1js">
      <bpmn:outgoing>Flow_0px6wn3</bpmn:outgoing>
      <bpmn:timerEventDefinition id="TimerEventDefinition_0cw97yh">
        <bpmn:timeDate xsi:type="bpmn:tFormalExpression">=dueDate</bpmn:timeDate>
      </bpmn:timerEventDefinition>
    </bpmn:boundaryEvent>
    <bpmn:userTask id="Activity_1blhfrh" name="CANCEL">
      <bpmn:extensionElements>
        <zeebe:userTask />
      </bpmn:extensionElements>
      <bpmn:incoming>Flow_027jamc</bpmn:incoming>
      <bpmn:outgoing>Flow_00rahlc</bpmn:outgoing>
    </bpmn:userTask>
  </bpmn:process>
  <bpmn:message id="Message_34h9gfv" name="execution_order_issuance_message">
    <bpmn:extensionElements>
      <zeebe:subscription correlationKey="=processInstanceId" />
    </bpmn:extensionElements>
  </bpmn:message>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="civil_partnership_payment_order_process">
      <bpmndi:BPMNShape id="Activity_08nwxpy_di" bpmnElement="create_payment_order_lnd">
        <dc:Bounds x="260" y="180" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Gateway_1kodaw1_di" bpmnElement="Gateway_0gapglz">
        <dc:Bounds x="405" y="195" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_1muwy3s_di" bpmnElement="Event_0a4lqk7">
        <dc:Bounds x="542" y="302" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="528" y="345" width="64" height="27" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Gateway_0m8tdol_di" bpmnElement="Gateway_0m8tdol" isMarkerVisible="true">
        <dc:Bounds x="655" y="195" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_0r62exq_di" bpmnElement="Activity_04wv1js">
        <dc:Bounds x="750" y="180" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Gateway_0lim3al_di" bpmnElement="Gateway_0lim3al" isMarkerVisible="true">
        <dc:Bounds x="905" y="195" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_0qavxjl_di" bpmnElement="Event_0dwy0xh">
        <dc:Bounds x="912" y="302" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="890" y="345" width="81" height="27" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_17nfw7p_di" bpmnElement="StartEvent_1">
        <dc:Bounds x="182" y="202" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="158" y="245" width="84" height="66" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_0x6vj41_di" bpmnElement="lms_announcement_finalization_lnd">
        <dc:Bounds x="510" y="180" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_1x9c0nb_di" bpmnElement="Activity_1blhfrh">
        <dc:Bounds x="380" y="280" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_16n813f_di" bpmnElement="Event_1xregc1">
        <dc:Bounds x="782" y="162" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Flow_0r414ln_di" bpmnElement="Flow_0r414ln">
        <di:waypoint x="218" y="220" />
        <di:waypoint x="260" y="220" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0rrh299_di" bpmnElement="Flow_0rrh299">
        <di:waypoint x="360" y="220" />
        <di:waypoint x="405" y="220" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_027jamc_di" bpmnElement="Flow_027jamc">
        <di:waypoint x="430" y="245" />
        <di:waypoint x="430" y="280" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_00rahlc_di" bpmnElement="Flow_00rahlc">
        <di:waypoint x="480" y="320" />
        <di:waypoint x="542" y="320" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_067wy8h_di" bpmnElement="Flow_067wy8h">
        <di:waypoint x="455" y="220" />
        <di:waypoint x="510" y="220" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0beouvl_di" bpmnElement="Flow_0beouvl">
        <di:waypoint x="610" y="220" />
        <di:waypoint x="655" y="220" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_17ccf9b_di" bpmnElement="Flow_17ccf9b">
        <di:waypoint x="680" y="195" />
        <di:waypoint x="680" y="140" />
        <di:waypoint x="330" y="140" />
        <di:waypoint x="330" y="180" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_01yqgzh_di" bpmnElement="Flow_01yqgzh">
        <di:waypoint x="705" y="220" />
        <di:waypoint x="750" y="220" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0ffz97k_di" bpmnElement="Flow_0ffz97k">
        <di:waypoint x="850" y="220" />
        <di:waypoint x="905" y="220" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_19qo79v_di" bpmnElement="Flow_19qo79v">
        <di:waypoint x="930" y="195" />
        <di:waypoint x="930" y="140" />
        <di:waypoint x="830" y="140" />
        <di:waypoint x="830" y="180" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="836" y="122" width="88" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0mkqmtb_di" bpmnElement="Flow_0mkqmtb">
        <di:waypoint x="930" y="245" />
        <di:waypoint x="930" y="302" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0px6wn3_di" bpmnElement="Flow_0px6wn3">
        <di:waypoint x="800" y="160" />
        <di:waypoint x="800" y="110" />
        <di:waypoint x="310" y="110" />
        <di:waypoint x="310" y="180" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="526" y="92" width="58" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

Hi @Sina_Mehrad - I think a critical piece of information that will help inform the model design is how the process should be canceled. Is the workflow of β€œA user logs into Tasklist, finds the waiting user task, claims it, then completes it” the correct workflow? Or might there be a button you click inside your application that triggers the cancellation? Or a message from an external system, like Kafka?

All of those scenarios can be modeled, but I think a good first step is to decide what your intended cancellation flow looks like and then design the model, rather than having the model decide the flow.

1 Like

Hi, thank you for your response. In my scenario, the flow should be canceled when a user clicks a button.

And do you know how to return to the previous step after a specific time? I want to learn the best practice.

@Sina_Mehrad - when a user clicks a button where?

Returning to a previous step depends on whether you want to rollback anything that happened in between, or if you just want the token to return to and repeat a previous step. You could use an interrupting timer boundary event and a link even to go back; or if you need to rollback anything, you would want to use a compensation event with the timer.

1 Like