Flowable getting started series article 54 - execution listener

Keywords: Java Flowable oa bpm

The execution listener allows you to execute external Java code or evaluate expressions when a specific event occurs during process execution. The events that can be captured are:

  • Start and end a process instance.
  • transformation.
  • Start and end activities.
  • Start and end a gateway.
  • Start and end intermediate events.
  • End the start event and start the end event.

The following process definition contains 3 execution listeners:

<process id="executionListenersProcess">
<extensionElements>
<flowable:executionListener
class="org.flowable.examples.bpmn.executionlistener.ExampleExecutionListenerOne"
event="start" />
</extensionElements>
<startEvent id="theStart" />
<sequenceFlow sourceRef="theStart" targetRef="firstTask" />
<userTask id="firstTask" />
<sequenceFlow sourceRef="firstTask" targetRef="secondTask">
<extensionElements>
<flowable:executionListener
class="org.flowable.examples.bpmn.executionListener.ExampleExecutionListenerTwo" />
</extensionElements>
</sequenceFlow>
<userTask id="secondTask" >
<extensionElements>
<flowable:executionListener
expression="${myPojo.myMethod(execution.event)}"
event="end" />
</extensionElements>
</userTask>
<sequenceFlow sourceRef="secondTask" targetRef="thirdTask" />
<userTask id="thirdTask" />
<sequenceFlow sourceRef="thirdTask" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>

Notifies the first execution listener when the process starts. The listener is an external Java class (exampleexecutionlistener one) and should implement an org.flowable.engine.delegate.ExecutionListener interface. When the event occurs (in this case, end), the method notify (executionlistenerexecution) is called.

public class ExampleExecutionListenerOne implements ExecutionListener {
	public void notify(ExecutionListenerExecution execution) throws Exception {
		execution.setVariable("variableSetInExecutionListener", "firstValue");
		execution.setVariable("eventReceived", execution.getEventName());
	}
}

You can also use a delegate class that implements the org.flowable.engine.delegate.JavaDelegate interface. These delegate classes can be reused in other structures, such as the delegate of serviceTask.

The second execution listener is called during the conversion. Note that the listener element does not define an event because the transition is only in the take event. When a listener is defined in an event transformation, the value in the property is ignored.

The last execution listener is called when the activity secondTask ends. Instead of using class in the listener declaration, expression defines a that a is evaluated / called when an event is triggered.

<flowable:executionListener expression="${myPojo.myMethod(execution.eventName)}" event="end" />

Like other expressions, execution variables are parsed and can be used. Because the execution implementation object has a property that exposes the event name, you can pass the event name to your method execution.eventName.

The execution listener also supports the use of a delegateExpression, similar to service tasks.

<flowable:executionListener event="start" delegateExpression="${myExecutionListenerBean}" />

Later, we also introduced a new execution listener, org.flowable.engine.impl.bpmn.listener.ScriptExecutionListener. This script execution listener allows you to execute a piece of script logic for execution listener events.

<flowable:executionListener event="start"
class="org.flowable.engine.impl.bpmn.listener.ScriptExecutionListener">
<flowable:field name="script">
<flowable:string>
def bar = "BAR"; // local variable
foo = "FOO"; // pushes variable to execution context
execution.setVariable("var1", "test"); // test access to execution instance
bar // implicit return value
</flowable:string>
</flowable:field>
<flowable:field name="language" stringValue="groovy" />
<flowable:field name="resultVariable" stringValue="myVar" />
</flowable:executionListener>

Perform field injection on the listener

Field injection can be applied when using an execution listener with the class attribute configured. This is exactly the same mechanism used in service task field injection, which contains an overview of the possibilities provided by field injection.

The following code snippet shows a simple example process with an execution listener injected with fields.

<process id="executionListenersProcess">
<extensionElements>
<flowable:executionListener
class="org.flowable.examples.bpmn.executionListener.ExampleFieldInjectedExecutionListener"
event="start">
<flowable:field name="fixedValue" stringValue="Yes, I am " />
<flowable:field name="dynamicValue" expression="${myVar}" />
</flowable:executionListener>
</extensionElements>
<startEvent id="theStart" />
<sequenceFlow sourceRef="theStart" targetRef="firstTask" />
<userTask id="firstTask" />
<sequenceFlow sourceRef="firstTask" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
public class ExampleFieldInjectedExecutionListener implements ExecutionListener {
	private Expression fixedValue;
	private Expression dynamicValue;
	public void notify(ExecutionListenerExecution execution) throws Exception {
		execution.setVariable("var", fixedValue.getValue(execution).toString() +
		dynamicValue.getValue(execution).toString());
	}
}

The class ExampleFieldInjectedExecutionListener connects two injection fields (one fixed and the other dynamic) and stores them in the procedure variable var.

@Deployment(resources = {
"org/flowable/examples/bpmn/executionListener/ExecutionListenersFieldInjectionProcess.bpmn20.xml"})
public void testExecutionListenerFieldInjection() {
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("myVar", "listening!");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
"executionListenersProcess", variables);
Object varSetByListener = runtimeService.getVariable(processInstance.getId(), "var");
assertNotNull(varSetByListener);
assertTrue(varSetByListener instanceof String);
// Result is a concatenation of fixed injected field and injected expression
assertEquals("Yes, I am listening!", varSetByListener);
}

The above article is from Pangu BPM Research Institute: http://vue.pangubpm.com/
Article translation submission: https://github.com/qiudaoke/flowable-userguide
For more articles, you can focus on WeChat official account:

Posted by flyankur on Fri, 12 Nov 2021 15:06:22 -0800