For people who needs same thing in SpringBoot, I wanted to share my solution.
Create an execution listener to run everytime a process goes through a sequence flow.
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.ExecutionListener;
import org.camunda.bpm.engine.delegate.Expression;
import org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity;
public class SequenceFlowHistoryListener implements ExecutionListener {
@Override
public void notify(DelegateExecution delegateExecution) throws Exception {
try {
// this method is called everytime a sequence flow is triggered
log.info("Properties " + delegateExecution.getId() + "," + delegateExecution.getCurrentTransitionId() + "," + delegateExecution.getProcessInstanceId());
// fire an historic event or do whatever you want
}catch (Exception e){
e.printStackTrace();
}
}
}
Then create a bpmn parser listener to set execution listener on each and every sequence flow in all process definitions.
import org.camunda.bpm.engine.impl.bpmn.listener.ClassDelegateExecutionListener;
import org.camunda.bpm.engine.impl.bpmn.parser.AbstractBpmnParseListener;
import org.camunda.bpm.engine.impl.bpmn.parser.BpmnParseListener;
import org.camunda.bpm.engine.impl.pvm.process.ScopeImpl;
import org.camunda.bpm.engine.impl.pvm.process.TransitionImpl;
import org.camunda.bpm.engine.impl.util.xml.Element;
public class CustomParseListener extends AbstractBpmnParseListener implements BpmnParseListener {
@Override
public void parseSequenceFlow(Element sequenceFlowElement, ScopeImpl scopeElement, TransitionImpl transition) {
super.parseSequenceFlow(sequenceFlowElement, scopeElement, transition);
try {
ClassDelegateExecutionListener classDelegateExecutionListener = new ClassDelegateExecutionListener(SequenceFlowHistoryListener.class, null);
transition.addListener("take", classDelegateExecutionListener);
} catch (Exception e){
e.printStackTrace();
}
}
}
Then wire parser listener to process engine configuration.
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.impl.bpmn.parser.BpmnParseListener;
import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin;
import org.camunda.bpm.spring.boot.starter.configuration.Ordering;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(Ordering.DEFAULT_ORDER -1)
public class MyCamundaProcessEnginePlugin implements ProcessEnginePlugin {
@Override
public void preInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
List<BpmnParseListener> postParseListeners = processEngineConfiguration.getCustomPostBPMNParseListeners();
if (postParseListeners == null) {
postParseListeners = new ArrayList<>();
processEngineConfiguration.setCustomPostBPMNParseListeners(postParseListeners);
}
postParseListeners.add(new CustomParseListener());
}
@Override
public void postInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
}
@Override
public void postProcessEngineBuild(ProcessEngine processEngine) {
}
}