Skip to content
Branch: master
Find file History
tmetzke chore(release): adjust examples for 7.12 release
* bpmn: remove Maven 1.x artifacts
* multi-tenancy: upgrade to WildFly
* process-engine-plugin: change listener event to assignment
* spring-nonpa: upgrade to WildFly
* spring-pa: upgrade to WildFly, refactor Arquillian WebArchive creation code

related to CAM-11015, CAM-11016, CAM-11017, CAM-11018, CAM-11019, CAM-11020, CAM-11099
Latest commit 00814ab Nov 26, 2019
Permalink
Type Name Latest commit message Commit time
..
Failed to load latest commit information.
docs chore(bpmn2.0): update modeler screenshots Nov 24, 2016
src chore(license): update license terms Apr 10, 2019
README.md chore(example): clarify example documentation May 27, 2019
pom.xml chore(release): adjust examples for 7.12 release Nov 26, 2019

README.md

Asynchronous Service Invocation

Warning: this example demonstrates an advanced usage pattern of the process engine based on internal (non-public) API. Similar behavior can be achieved using a send task and a receive task. The latter option is recommended in most usecases.

This quickstart demonstrates how to implement an asynchronous service invocation using a Signallable Activity Behavior. We learn

  • How to implement the Signallable Activity Behavior Interface,
  • How to reference a Signallable Activity Behavior Implementation from BPMN 2.0

After having looked through the code, you will understand the behavior of an asynchronous service invocation in case of

  • Successful invocation
  • A service failure.

Show me the important parts!

The process model is composed of three tasks:

Process Model

  • Wait State Before: initially, the process instance is waiting here.
  • Asynchronous Service Task: the service task invoked by the process engine in an asynchronous fashion.
  • Wait State After: in case of successful invocation, the process instance will advance to here.

Create a Signallable Activity Behavior Implementation

Create a new Java Class extending org.camunda.bpm.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior:

public class AsynchronousServiceTask extends AbstractBpmnActivityBehavior {

  public static final String EXECUTION_ID = "executionId";

  public void execute(final ActivityExecution execution) throws Exception {

    // Build the payload for the message:
    Map<String, Object> payload = new HashMap<String, Object>(execution.getVariables());
    // Add the execution id to the payload:
    payload.put(EXECUTION_ID, execution.getId());

    // Publish a message to the outbound message queue. This method returns after the message has
    // been put into the queue. The actual service implementation (Business Logic) will not yet
    // be invoked:
    MockMessageQueue.INSTANCE.send(new Message(payload));

  }

  public void signal(ActivityExecution execution, String signalName, Object signalData) throws Exception {

    // leave the service task activity:
    leave(execution);
  }

}

The actual business logic is placed inside a different class and invoked by the message queue:

public class BusinessLogic {

  public static final String PRICE_VAR_NAME = "price";
  public static final float PRICE = 199.00f;

  public void invoke(Message message, ProcessEngine processEngine) {

    // Process the message and send a callback.

    // Extract values from payload:
    Map<String, Object> requestPayload = message.getPayload();
    // the execution id is used as correlation identifier
    String executionId = (String) requestPayload.get(AsynchronousServiceTask.EXECUTION_ID);

    // Send the callback to the process engine. In this example we send
    // a synchronous callback. We could also send an asynchronous callback
    // using a message queue.
    Map<String, Object> callbackPayload = Collections.<String,Object>singletonMap(PRICE_VAR_NAME, PRICE);
    processEngine.getRuntimeService().signal(executionId, callbackPayload);

  }
}

Reference the Signallable Activity Behavior from BPMN 2.0

The Java Deleagte can be referenced using the class attribute from the process engine Namespace:

<bpmn2:serviceTask id="serviceTaskActivity"
  camunda:class="org.camunda.quickstart.servicetask.invocation.AsynchronousServiceTask"
  name="Asynchronous Service Task">

Using the camunda Modeler, you can configure the service task using the properties panel:

Configure Signallable Activity Behavior using the camunda Modeler

Invocation Semantics

The SignallableActivityBehavior provides two methods: execute() and signal():

Asynchronous Service Invocation Sequence

  • The execute(ActivityExecution) method is invoked when the service task is entered. It is typically used for sending an asynchronous message to the actual service (Business Logic). When the method returns, the process engine will NOT continue execution. The SignallableActivityBehavior acts as a wait state.

  • The signal(ActivityExecution, String, Object) method is invoked as the process engine is being triggered by the callback. The signal method is responsible for leaving the service task activity.

The asynchronous nature of the invocation decouples the process engine from the service implementation. The process engine does not propagate any thread context to the service implementation. Most prominently, the service implementation is not invoked in the context of the process engine transaction. On the contrary, from the point of view of the process engine, the SignallableActivityBehavior is a wait state: after the execute() method returns, the process engine will stop execution, flush the state of the execution to the database and wait for the callback to occur.

If a failure occurs in the service implementation (Business Logic), the failure will not cause the process engine to roll back. The reason being that the service implementation is not directly invoked by the process engine and does not participate in the process engine transaction.

Additionally, it has to be noted that signal() can't create an Incident if an error occurred while running the Business Logic.

How to use it?

  1. Checkout the project with Git
  2. Import the project into your IDE
  3. Inspect the sources and run the unit test.
You can’t perform that action at this time.