Register Execution Listener via BpmnParseHandler

Hello,

I’m attempting to register execution listeners on my BPMN assets to achieve an aspect-oriented approach to implementing global behavior without globally modifying my library of BPMN XML. I was thrilled to find an approach for this in the Open Source Documentation. Unfortunately, the execution listeners I register via the BpmnParseHandler are never triggered. If I instead manually create the execution listeners with <extensionElements> coded directly into the XML, then my listeners behave as expected.

I’ve put together a reproducible test that isolates the problem I’m seeing. If you take a look at the two screenshots in the project’s README, it’s clear that the BpmnParseHandler successfully registers extension elements that identify my listener class in the in-memory BPMN models, but those extensions do not translate into listener instances in the Process.getExecutionListeners() list (for instance).

I’ve searched this forum for mention of a similar problem, but the only post I’ve found with “BpmnParse” in the title is currently unanswered.

The problem seems to be that my BpmnParseHandler is adding the extension elements too late in the parsing process. By the time BpmnParse.execute() calls BpmnParse.applyParseHandlers(), the BpmnXMLConverter.convertToBpmnModel() call has already translated extension elements to execution listeners, and so my dynamic XML addendums go unrecognized.

Am I on the right track for registering dynamic execution listeners, or am I missing the point?

Best Regards,
Chase

Hey @chaserb,

The problem is that you are adding an extension element instead of a listener. What you need to do is something like:

public class CustomPreParseHandler implements BpmnParseHandler {

    private final FlowableListener startListener;
    private final FlowableListener endListener;

    public CustomPreParseHandler() {
        startListener = new FlowableListener();
        startListener.setEvent(ExecutionListener.EVENTNAME_START);
        startListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
        startListener.setImplementation("test.bpmn_parser.CustomExecutionListener");

        endListener = new FlowableListener();
        endListener.setEvent(ExecutionListener.EVENTNAME_END);
        endListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
        endListener.setImplementation("test.bpmn_parser.CustomExecutionListener");
    }

    @Override
    public Collection<Class<? extends BaseElement>> getHandledTypes() {
        return List.of(Process.class, ScriptTask.class);
    }

    @Override
    public void parse(final BpmnParse bpmnParse, final BaseElement element) {
        if (element instanceof Process process) {
            process.getExecutionListeners().add(startListener);
        } else if (element instanceof FlowElement flowElement) {
            flowElement.getExecutionListeners().add(endListener);
        }
    }

}

Cheers,
Filip

1 Like