Interface ProcessingLifecycleInterceptor
UnitOfWork, on the very thread
that runs the action.
Every registered phase action (INVOCATION, PREPARE_COMMIT, COMMIT, AFTER_COMMIT, ...), as well as the completion- and
error-handler dispatch sites, passes through this interceptor. This makes it the single choke point for bridging
thread-bound state, such as distributed tracing context, MDC, or security context, into the segments that the
framework executes on its own work scheduler threads.
The three dispatch kinds are exposed as three separate, all-abstract methods,
interceptPhase(ProcessingContext, Phase, Supplier),
interceptCompletion(ProcessingContext, Runnable), and
interceptError(ProcessingContext, Phase, Throwable, Runnable), rather than a single method discriminated by
a nullable flag. The compiler therefore forces every implementation to consider all three sites, removing the risk
of an implementation that silently covers phase actions while missing the completion- or error-handler dispatch.
Implementations that want to apply the same behavior uniformly to all three kinds (the common case for state-bridging
infrastructure such as a tracing binding) should use intercept(UniformInterceptor) instead of implementing
this interface directly.
No interceptor is installed by default: UnitOfWorkConfiguration.defaultValues() leaves the interceptor
null, and the UnitOfWork then runs actions directly, adding no behavior and no overhead. An
interceptor is meant to be installed by infrastructure (for example a tracing binding) through
UnitOfWorkConfiguration.addLifecycleInterceptor(ProcessingLifecycleInterceptor), which composes contributors
via andThen(ProcessingLifecycleInterceptor) so multiple installers never clobber one another.
Implementations run on the action's thread and MUST restore any thread-bound state they mutate before returning, regardless of the action's outcome (typically via try-with-resources).
Evolution policy: should a future minor release introduce another dispatch-kind method, its default
implementation MUST delegate to an existing method of this interface (safe-by-default), never pass through the action
unintercepted (skip-by-default). This preserves the guarantee that a wrap-everything implementor (any implementation
obtained through intercept(UniformInterceptor)) keeps covering every dispatch site across releases.
- Since:
- 5.3.0
- Author:
- Mateusz Nowak
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic interfaceKind-agnostic interceptor applied uniformly to all dispatch sites byintercept(UniformInterceptor). -
Method Summary
Modifier and TypeMethodDescriptiondefault ProcessingLifecycleInterceptorComposes this interceptor with theotherone, invokingthison the outside andotheron the inside (closest to the action), per dispatch kind.Creates aProcessingLifecycleInterceptorthat applies the giveninterceptoruniformly to all three dispatch kinds: phase actions, completion-handler dispatch, and error-handler dispatch.voidinterceptCompletion(ProcessingContext context, Runnable action) Invoked on the thread that executes theaction, immediately around it.voidinterceptError(ProcessingContext context, @Nullable ProcessingLifecycle.Phase failedPhase, Throwable cause, Runnable action) Invoked on the thread that executes theaction, immediately around it.interceptPhase(ProcessingContext context, ProcessingLifecycle.Phase phase, Supplier<CompletableFuture<?>> action) Invoked on the thread that executes theaction, immediately around it.
-
Method Details
-
interceptPhase
CompletableFuture<?> interceptPhase(ProcessingContext context, ProcessingLifecycle.Phase phase, Supplier<CompletableFuture<?>> action) Invoked on the thread that executes theaction, immediately around it. This is the seam for bridging thread-bound state (tracing context, MDC, security) into phase actions registered in a lifecycle phase.- Parameters:
context- theProcessingContextof theUnitOfWorkexecuting the actionphase- theProcessingLifecycle.Phasethe action executes inaction- the action to execute, returning aCompletableFuturethat completes when the action is done- Returns:
- the result of executing the
action
-
interceptCompletion
Invoked on the thread that executes theaction, immediately around it. This is the seam for bridging thread-bound state into awhenComplete-handler dispatch, running after the lifecycle completed successfully.- Parameters:
context- theProcessingContextof theUnitOfWorkwhose completion handler is dispatchedaction- the completion-handler dispatch to execute
-
interceptError
void interceptError(ProcessingContext context, @Nullable ProcessingLifecycle.Phase failedPhase, Throwable cause, Runnable action) Invoked on the thread that executes theaction, immediately around it. This is the seam for bridging thread-bound state into anonError-handler dispatch, running after the lifecycle failed.- Parameters:
context- theProcessingContextof theUnitOfWorkwhose error handler is dispatchedfailedPhase- theProcessingLifecycle.Phasewhose action failed, ornullwhen the failure preceded the first phasecause- the failure that moved the lifecycle into its error stateaction- the error-handler dispatch to execute
-
intercept
static ProcessingLifecycleInterceptor intercept(ProcessingLifecycleInterceptor.UniformInterceptor interceptor) Creates aProcessingLifecycleInterceptorthat applies the giveninterceptoruniformly to all three dispatch kinds: phase actions, completion-handler dispatch, and error-handler dispatch.This is the shape most infrastructure contributors need: state-bridging behavior (restoring thread-locals, activating a live span, ...) that does not depend on which kind of dispatch is being intercepted, expressed as a single lambda that can never under-cover a dispatch site.
- Parameters:
interceptor- the kind-agnostic interceptor applied to every dispatch site- Returns:
- a
ProcessingLifecycleInterceptordelegating every dispatch kind tointerceptor
-
andThen
Composes this interceptor with theotherone, invokingthison the outside andotheron the inside (closest to the action), per dispatch kind. Composition ensures multiple contributors never clobber each other.- Parameters:
other- the interceptor to invoke inside this one- Returns:
- a composed
ProcessingLifecycleInterceptor
-