templates: type the correlateMessageEvent catch in Abort and Wait, and the no-subscription miss behind it (#7230) - #7308
Merged
Conversation
…d the no-subscription miss behind it (#7230) The #7145 fix typed the blanket `catch (RuntimeException)` in AbortOnDelete.java.template only; Abort.java.template and Wait.java.template still swallowed every RuntimeException around `Process.correlateMessageEvent`. A correlation that fails because the engine is down, the tenant scope is wrong or the message name was mis-generated was indistinguishable from the expected "the instance is not parked here" - and a wait that is never resumed is exactly the incident an operator has to explain later with nothing in the log. Typing the catch needed the platform to report the expected miss as a type first: BpmProviderFlowable.correlateMessageEvent dereferenced a null Execution when the instance carried no subscription for the message, so the "not parked" outcome arrived as a NullPointerException - not something a listener can honestly single out. It now throws the same IllegalArgumentException the validator raises for an already-ended instance. Both templates then follow the AbortOnDelete recipe: IllegalArgumentException is the quiet, expected miss, logged at debug with its throwable; anything else is logged at warn with its throwable, naming the consequence (a flow still running over a record whose status says it is over; an instance that stays parked forever). Fail-soft, but never silent. The two intent ITs that compile these templates assert the two catch shapes and that the old empty catch is gone. Fixes #7230 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
master landed the same #7230 fix (BpmProviderFlowable's typed miss, the two templates and the IntentEmissionCoverageIT assertions), so those four files resolve to master's version verbatim - its assertions are the stricter pair (they also require the throwable in the debug log). What survives from this branch is the half master did not touch: IntentEngineIT still asserted only `catch (RuntimeException`, which the new two-catch shape passes trivially. It now checks the typed miss, the warn-with-throwable, and that the old empty catch is gone - on both the wait and the abort handler. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
What
#7184(#7145) typed the blanketcatch (RuntimeException)inAbortOnDelete.java.template, but the two siblings that wrapProcess.correlateMessageEventkept swallowing everything:events/Abort.java.template—catch (RuntimeException notAborting) {}events/Wait.java.template—catch (RuntimeException notParked) {}A correlation that fails because the engine/DB is down, the tenant scope is wrong, or the message name was mis-generated was indistinguishable from the expected "the instance is not parked here" — and a
waitstep that is never resumed is exactly the kind of incident an operator has to explain later with nothing in the log.The platform half
Typing the catch needed a typed miss to catch.
BpmProviderFlowable.correlateMessageEventqueried the execution carrying the message subscription and then calledexecution.getId()— so an instance that is running but not subscribed to the message surfaced as aNullPointerException, which no listener can honestly single out. It now throws the sameIllegalArgumentExceptionthatvalidateProcessInstanceIdraises for an instance that has already ended (or belongs to another tenant), naming both the instance and the message.The template half
Both templates follow the
AbortOnDeleterecipe:The
warnmessage names the consequence in each case: a flow still running over a record whose status says it is over (abort), an instance that stays parked forever (wait). Fail-soft, but never silent. The class javadocs say the same.Verification
IntentEngineIT— 77/77 green. Extended: the two catch shapes plusassertFalsethat the old emptycatch (RuntimeException notParked/notAborting)is gone.IntentEmissionCoverageIT— green. Same assertions onRfqFlowAwaitReplyWaitandApprovalFlowAbort. Both ITs compile the generated handlers, so the new catch order is checked by javac, not only bycontains.components/engine/engine-bpm-flowableunit suite — 35/35 green.formatter:validategreen on the changed modules with the formatter cache wiped.Not run: the full reactor test suite, and no runtime test exercises a correlation against a live down-engine (there is no existing harness for it).
Sibling sweep
Grepped every
*.templatefor the same shape: the remainingcatch (RuntimeException e)blocks inTrigger.java.template,Repository.java.templateand the threeEntity*Controllertemplates all log the throwable already.correlateMessageEventis called from exactly these two templates.Fixes #7230
🤖 Generated with Claude Code