Comprehensive Guide to Using Listeners in Camunda BPM

Introduction

Camunda BPM offers powerful capabilities for customizing process behavior and handling events through the use of listeners. In this guide, we will explore how to effectively utilize execution listeners and task listeners in Camunda BPM processes. We’ll also demonstrate how to trigger subprocesses from the main process using message events, along with scripting examples in Groovy.

In Camunda BPM, both execution listeners and task listeners are used to execute custom logic at specific points during the execution of a business process. However, they serve different purposes and are triggered at different stages of the process.

Execution and Task Listeners

  1. Execution Listeners:
    • Execution listeners are attached to BPMN elements such as activities, gateways, and events.
    • They are invoked when certain events occur during the lifecycle of the BPMN element, such as when the element is started, completed, or enters a certain state.
    • Execution listeners can be used to perform actions such as logging, updating variables, invoking external services, or even controlling the flow of the process based on certain conditions.
    • Common use cases for execution listeners include logging, auditing, and customizing the behavior of BPMN elements.
  2. Task Listeners:
    • Task listeners are specifically associated with user tasks within a BPMN process.
    • They are triggered when certain events occur related to the user task, such as when the task is created, assigned, completed, or deleted.
    • Task listeners are often used to perform actions related to user interaction, such as sending notifications, updating task properties, or integrating with external systems.
    • Common use cases for task listeners include sending emails, updating task assignments, or performing custom validation before task completion.

Description of Example

Here’s a brief description of the scenario involving the main process and the subprocess:

Main Process:

  • Trigger: The main process is triggered when a QR code of a battery is scanned.
  • Purpose: Its purpose is to orchestrate the handling of different types of batteries by triggering appropriate subprocesses.
  • Flow: After the QR code is scanned, a message event is caught, leading to the execution of the subprocess.
  • Tasks: The main process doesn’t involve specific tasks but rather serves as an orchestrator for the subprocesses.

Subprocess: “Battery Handling”

  • Purpose: This subprocess is designed to handle tasks specific to the type of battery scanned in the main process.
  • Tasks:
    • Send Notification Task: Upon entry into the subprocess, a notification is sent to the user. A task listener is used to start a timer for 5 minutes upon task completion.
    • Conduct Survey Task: After the timer expires, a survey is conducted. An execution listener is used to proceed to the next task when a variable is updated from the survey response.
    • Generate Report Task: Finally, based on the survey response, a report is generated.

This subprocess encapsulates the actions necessary for handling a specific type of battery, ensuring that tasks are executed in a timely manner and relevant reports are generated based on user feedback.

Setting up the Main Process

Let’s start by defining the main process, which will be triggered when the appropriate QR code of a battery is scanned. Here’s a code in XML:

<process id="mainProcess" isExecutable="true">
    <!-- Define start event -->
    <startEvent id="startEvent" />
    <!-- Configure message event -->
    <intermediateCatchEvent id="messageEvent" name="Battery Scanned">
        <messageEventDefinition messageRef="batteryMessage" />
    </intermediateCatchEvent>
    <!-- Define sequence flow to subprocess -->
    <sequenceFlow id="toSubprocess" sourceRef="messageEvent" targetRef="subProcess" />
</process>

Subprocesses and User Tasks

Now, let’s design subprocesses tailored to specific battery types and implement user tasks within them:

<subProcess id="subProcess" name="Battery Handling">
    <!-- Define user task to send notification -->
    <userTask id="sendNotificationTask" name="Send Notification">
        <!-- Configure task listener for task completion -->
        <extensionElements>
            <camunda:taskListener event="complete" class="org.camunda.bpm.example.NotificationTaskListener" />
        </extensionElements>
    </userTask>
    <!-- Define sequence flow to survey task -->
    <sequenceFlow id="toSurveyTask" sourceRef="sendNotificationTask" targetRef="surveyTask" />
    <!-- Define user task to conduct survey -->
    <userTask id="surveyTask" name="Conduct Survey">
        <!-- Configure execution listener for variable update -->
        <extensionElements>
            <camunda:executionListener event="update" class="org.camunda.bpm.example.SurveyUpdateListener" />
        </extensionElements>
    </userTask>
    <!-- Define sequence flow to report generation -->
    <sequenceFlow id="toReportTask" sourceRef="surveyTask" targetRef="generateReportTask" />
    <!-- Define end event -->
    <endEvent id="endEvent" />
</subProcess>

Using Task Listeners

Implement task listeners to handle events such as task completion. Here is the code in Groovy:

// Groovy script for task listener to start timer
class NotificationTaskListener implements TaskListener {
    void notify(DelegateTask delegateTask) {
        // Start timer for 5 minutes
        delegateTask.setDueDate(calculateDueDate(5))
    }
}

Handling Timer Events

Handle timer events triggered by task completion to send surveys to users. In XML:

<boundaryEvent id="timerEvent" attachedToRef="sendNotificationTask">
    <timerEventDefinition>
        <timeDuration>${dueDate}</timeDuration>
    </timerEventDefinition>
</boundaryEvent>

Using Execution Listeners

Implement execution listeners to respond to variable updates:

// Groovy script for execution listener to proceed to the next task
class SurveyUpdateListener implements ExecutionListener {
    void notify(DelegateExecution execution) {
        // Proceed to the next task when variable is updated
        execution.getProcessEngineServices().getRuntimeService()
            .createMessageCorrelation("surveyComplete")
            .setVariable("surveyAnswer", execution.getVariable("surveyAnswer"))
            .correlate()
    }
}

Generating Reports

Finally, generate reports based on survey responses. In Groovy:

// Groovy script for report generation
class ReportGenerator {
    void generateReport(String surveyAnswer) {
        // Generate report based on survey response
    }
}

Conclusion

In this guide, we’ve explored the use of execution listeners and task listeners in Camunda BPM processes, along with triggering subprocesses and scripting with Groovy. By leveraging these capabilities, you can efficiently orchestrate complex business processes and automate tasks with ease.

Using Groovy for scripting in Camunda BPM provides flexibility and simplicity, especially for smaller scripts or tasks. Groovy scripts can be directly embedded within BPMN models or referenced externally, depending on your preference and project requirements.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *