@thorben @GotnOGuts
Actually registering an execution listener on the user task works.
If anything missing, please comment!
ParseListenerPlugin:
@Component
public class ParseListenerPlugin extends AbstractProcessEnginePlugin {
@Override
public void preInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
List<BpmnParseListener> preParseListeners = processEngineConfiguration.getCustomPreBPMNParseListeners();
if (preParseListeners == null) {
preParseListeners = new ArrayList<>();
processEngineConfiguration.setCustomPreBPMNParseListeners(preParseListeners);
}
preParseListeners.add(new UserTaskParseListener());
}
}
UserTaskParseListener:
public class UserTaskParseListener extends AbstractBpmnParseListener {
@Override
public void parseUserTask(Element userTaskElement, ScopeImpl scope, ActivityImpl activity) {
activity.addListener(ExecutionListener.EVENTNAME_END, new UserTaskEndExecutionListener());
}
UserTaskEndExecutionListener:
public class UserTaskEndExecutionListener implements ExecutionListener {
private static final Logger LOG = LoggerFactory.getLogger(UserTaskEndExecutionListener.class);
@Override
public void notify(DelegateExecution delegateExecution) throws Exception {
LOG.info("*************** UserTaskEndExecutionListener ***************");
ExecutionEntity executionEntity = (ExecutionEntity) delegateExecution;
LOG.info("executionEntity: " + executionEntity);
boolean externallyTerminated = executionEntity.isExternallyTerminated();
LOG.info("externallyTerminated: " + externallyTerminated);
boolean canceled = executionEntity.isCanceled();
LOG.info("cancelled: " + canceled);
delegateExecution.setVariableLocal("somelocalvar", "somelocalval");
}
}
When process deletion happens, it logs like this:
*************** UserTaskEndExecutionListener ***************
executionEntity: ScopeExecution[69776c60-fc0a-11ed-b376-a08069929d2b]
externallyTerminated: true
cancelled: true
When the user task timeouts because of the timer boundary event, it logs like this:
*************** UserTaskEndExecutionListener ***************
executionEntity: ScopeExecution[b378955f-fc0a-11ed-b376-a08069929d2b]
externallyTerminated: false
cancelled: true
So… If externallyTerminated: true
and cancelled: true
I know that the user task canceled because of the process deletion, there is a manual intervention! And, if externallyTerminated: false
and cancelled: true
, then the user task most probably timed out. Notice the “most probably” part! Being externallyTerminated: false
and cancelled: true
means always the timeout?
I changed the process a little bit.

While the token is waiting on “user task 1” and the timer boundary event has not expired yet, when I correlate a message, that matches the message boundary event, to the process, UserTaskEndExecutionListener prints the log as follows:
*************** UserTaskEndExecutionListener ***************
executionEntity: ScopeExecution[c54d3750-fc18-11ed-9ad1-a08069929d2b]
externallyTerminated: false
cancelled: true
It’s the same as when the user task is actually timed out. UserTaskEndExecutionListener will always print the same log for all kinds of “Interrupting” type events added to the user task. Right?
In this case, I need to distinguish that “user task 1” is “canceled” not because of the message boundary event, but because of the timer boundary event. How can I do that?
Thanks.