Snapshot send-event task expressions at scheduling time for async jobs#4207
Closed
kle-dev wants to merge 1 commit intoflowable:mainfrom
Closed
Snapshot send-event task expressions at scheduling time for async jobs#4207kle-dev wants to merge 1 commit intoflowable:mainfrom
kle-dev wants to merge 1 commit intoflowable:mainfrom
Conversation
The async send-event job re-evaluates eventInParameter and channelKey
expressions in a worker thread, which loses every thread-local backed
context: ${authenticatedUserId} resolves to null, custom security beans
return empty values, tenant-scoped helpers fall back to defaults, and so
on. Behaviour diverges from sendSynchronously=true even though both
paths end at the same dispatch.
Resolve every expression in the scheduling thread (where the original
variables, authenticated user, beans and other context are still
available) and persist the result as a JSON snapshot on
JobEntity.customValues. The async handler reads the snapshot, exposes
it on the command context and lets the activity behaviour dispatch the
captured values verbatim — no expression is evaluated in the worker.
Async sending is now semantically identical to synchronous sending
regardless of which thread-local context the eventInParameters depend
on. Jobs scheduled by an older engine fall back to the legacy
re-evaluation path so in-flight upgrades stay safe.
Tests: testSendEventWithAuthenticatedUserExpression keeps the original
authenticated-user case; testSendEventWithThreadLocalBeanExpression
adds a custom bean backed by a ThreadLocal to demonstrate the fix is
not specific to Authentication.
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
Replaces #4205 with a fix at the root of the problem.
The async send-event job today re-evaluates
eventInParameterandchannelKeyexpressions in a worker thread, losing every thread-local backed context:${authenticatedUserId}resolves tonull, custom security beans return empty values, tenant-scoped helpers fall back to defaults. Behaviour diverges fromsendSynchronously=trueeven though both paths end at the same dispatch. #4205 fixes the specific${authenticatedUserId}symptom by capturing/restoring the authenticated user across the job boundary, but anything else context-dependent stays broken.This PR resolves every expression in the scheduling thread — where variables, authenticated user, beans and other context are still available — and persists the result as a JSON snapshot on
JobEntity.customValues. The async handler reads the snapshot, exposes it on the command context and letsSendEventTaskActivityBehaviordispatch the captured values verbatim. No expression is evaluated in the worker thread.Async sending is now semantically identical to synchronous sending regardless of which thread-local context the
eventInParametersdepend on. Jobs scheduled by an older engine fall back to the legacy re-evaluation path so in-flight upgrades stay safe.Changes
SendEventTaskActivityBehavior— async branch captures channel keys + payload values viawriteSnapshotintocustomValues; sync branch consumes the snapshot exposed by the handler if present, otherwise resolves expressions as before.getChannelModelsis split intoresolveChannelKeys+resolveChannelModelsfor reuse.AsyncSendEventJobHandler— readscustomValues, parses the JSON snapshot and exposes it on theCommandContextunderSNAPSHOT_ATTRIBUTE. The PR Propagate authenticated user when send-event task is sent asynchronously #4205 mechanism (jobHandlerConfigurationcarrying the authenticated user) is no longer needed.SendEventTaskTest— keepstestSendEventWithAuthenticatedUserExpressionfrom Propagate authenticated user when send-event task is sent asynchronously #4205 as a regression case; addstestSendEventWithThreadLocalBeanExpressionwhich registers a custom bean backed by aThreadLocal, proving the fix is not specific toAuthentication.Notes on payload value round-trip
Payload values are persisted via the engine's
ObjectMapper. Strings, numbers, booleans, JSON nodes andnullround-trip losslessly. Custom POJOs / dates pass through Jackson's default serialization — the same path the existing JSON outbound serializer would use, so the observable channel output is unchanged for the common cases.Test plan
mvn test -pl modules/flowable-engine -Dtest=SendEventTaskTest— 14/14 passmvn test -pl modules/flowable-engine -Dtest='*EventRegistry*,*SendEvent*,*ReceiveEvent*'— 81/81 pass