Customizable BPMN EventDefinitions and CMMN EventListeners#4206
Open
filiphr wants to merge 9 commits intoflowable:mainfrom
Open
Customizable BPMN EventDefinitions and CMMN EventListeners#4206filiphr wants to merge 9 commits intoflowable:mainfrom
filiphr wants to merge 9 commits intoflowable:mainfrom
Conversation
Allow consumers to register custom EventDefinition / EventListener types end-to-end: parser + writer registration hooks on the BPMN side, a discriminator registry on the CMMN side, and an EventDefinition.getSupported Locations() set that the placement validators consult instead of hard-coded instanceof chains. The legacy <flowable:eventType> child is parsed into a typed EventRegistryEventDefinition. Tests cover the full register-deploy- execute path on both engines.
…se handlers Replace the inline instanceof cascade in StartEventParseHandler with a single parseElement(eventDefinition) delegation, matching the pattern in BoundaryEventParseHandler and IntermediateCatchEventParseHandler. Each per-EventDefinition handler now installs the event-sub-process behavior alongside its IntermediateCatch / Boundary cases, so custom EventDefinitions go through the same path as the built-ins.
…Event behavior Each event-sub-process StartEvent ActivityBehavior now owns its full lifecycle via a new EventSubProcessStartEventActivityBehavior interface (initializeEventSubProcessStart(context)). The five built-in subscription registering behaviors (Message, Signal, Timer, EventRegistry, VariableListener) absorb the bodies of the corresponding handle... helpers from ProcessInstanceHelper, which collapses to a single delegated call. The context exposes createEventScopeChildExecution(), createEventSubscriptionBuilder(execution), and record callbacks that preserve the two-pass message/signal-waiting dispatch.
…yBehavior Each process-level start event now owns its full deploy lifecycle via a new ProcessLevelStartEventActivityBehavior interface (deploy + undeploy), plus typed deploy/undeploy contexts and four built-in behaviors (Message, Signal, Timer, EventRegistry). BpmnDeploymentHelper iterates start events and the EventSubscriptionManager / TimerManager classes are deleted. A new findEventSubscriptionsByTypesAndProcessDefinitionId finder runs a single SQL with EVENT_TYPE_ IN (...), so cleanup is one DB round-trip regardless of how many handler types the previous process definition declared.
…dlers Replace IntermediateThrowEventParseHandler's instanceof cascade with a parseElement(eventDefinition) delegation. Signal and Escalation parse handlers gain a ThrowEvent branch (Compensate already had one); the None-throw path stays inline.
Replace EndEventParseHandler's instanceof cascade for Error / Escalation / Terminate / Cancel with a parseElement(eventDefinition) delegation. The per-EventDefinition handlers gain EndEvent branches and a new TerminateEventDefinitionParseHandler covers Terminate's only valid placement. None-end stays inline.
DeploymentProcessDefinitionDeletionManagerImpl now iterates the previous process definition's top-level start events and calls behavior.deploy() instead of dispatching by instanceof. The deploy context gains an isRestoringPreviousVersion() flag so MessageStartEventActivityBehavior can skip its duplicate-subscription guard — the just-deleted PD's row is still in the in-session cache because the bulk delete is queued, not flushed.
Mirror the BPMN ProcessLevelStartEventActivityBehavior pattern on the CMMN side: a CaseDefinitionStartLifecycleHandler attached to the Case at parse time owns its deploy/undeploy. The deploy context has an isRestoringPreviousVersion() flag for parity, and an EventRegistryCaseDefinitionStartLifecycleHandler is installed by default when case.startEventType is set. A new findEventSubscriptionsByTypesAndScopeDefinitionId finder lets CmmnDeployer issue a single bulk-delete after the undeploy iteration.
…Locations() Align EndEventValidator and IntermediateThrowEventValidator with the four already-refactored placement validators so all six EventDefinitionLocation values are enforced. Built-ins keep their existing behavior; custom EventDefinitions declaring END_EVENT or INTERMEDIATE_THROW_EVENT support are now valid at those placements.
b92e083 to
c6d7dbb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds end-to-end extensibility for custom BPMN
EventDefinitions and CMMNEventListeners, and refactors the dispatch / deploy lifecycle / placementvalidation paths around it so the built-ins go through the same code paths
as the customs.
What's new (extensibility surface)
addCustomChildElementParserregistersa parser at engine init so custom
<flowable:*>children parse into atyped
EventDefinition;addCustomEventDefinitionWriterregisters thematching XML writer for round-trip serialization. A new
CustomBpmnEventDefinitionmarker interface flags subclasses that routethrough the extension-elements path.
GenericEventListenerXmlConverterkeyed byflowable:eventType, with acustomEventListenerTypeFactoriesslot onCmmnEngineConfiguration.flowable:eventType="event"is now a built-in discriminator value thatproduces an
EventRegistryEventListenerdirectly (alongsidesignal,variable,intent,reactivate); the legacy<flowable:eventType>X</flowable:eventType>extension element stillworks.
EventDefinition#getSupportedLocations(): each subtype declares theimmutable set of placements (start / event-sub-process start /
intermediate catch / boundary / end / intermediate throw) it's valid at;
all six placement validators consult this set instead of hard-coded
instanceofchains.Refactors that fall out of the design
EventSubProcessStartEventActivityBehaviorand owninitializeEventSubProcessStart(...). The five built-in registeringbehaviors (Message, Signal, Timer, EventRegistry, VariableListener)
absorb the bodies of the corresponding
handle...helpers inProcessInstanceHelper, which collapses to a single delegated call.ProcessLevelStartEventActivityBehaviorand owndeploy(...)/undeploy(...).BpmnDeploymentHelperiterates start events; theEventSubscriptionManagerandTimerManagerclasses are deleted.DeploymentProcessDefinitionDeletionManagerImpldelegates restore-after-delete to
behavior.deploy(...)with anisRestoringPreviousVersion()flag in the deploy context.StartEventParseHandler,IntermediateThrowEventParseHandler, andEndEventParseHandlernolonger have
instanceofcascades — each routes throughparseElement(eventDefinition)like the boundary / catch handlersalready did.
CaseDefinitionStartLifecycleHandlerattached tothe
Caseat parse time mirrors the BPMN process-level pattern. Thebuilt-in
EventRegistryCaseDefinitionStartLifecycleHandlerisinstalled by default when
case.startEventTypeis set.findEventSubscriptionsByTypesAndProcessDefinitionId/findEventSubscriptionsByTypesAndScopeDefinitionIdfinders run asingle SQL with
EVENT_TYPE_ IN (...), so deploy-time cleanup isone DB round-trip regardless of how many handler types the previous
definition declared.
Breaking changes
EventRegistryEventListenerno longer extendsGenericEventListener(both extend
EventListenerdirectly now). Downstream code that doesinstanceof GenericEventListenerorfindPlanItemDefinitionsOfType(GenericEventListener.class)to enumerateevent-registry listeners must switch to
EventRegistryEventListener(ormatch both, where the runtime distinction matters).