Ecotone
provide possibility to handle cross cutting concerns via Interceptors
.
Interceptor
as name the suggest, intercepts the process of handling the message.
You may enrich the message, stop or modify usual processing cycle, call some shared functionality, add additional behavior to existing code without modifying the code itself. Ecotone.
The precedence is done within a specific interceptor type. Pointcut
attribute, which describes for specific interceptor, which endpoints it should intercept.CLASS_NAME
- indicates intercepting specific class or interface or class containing attribute on method or class levelexpression||expression
- Indicating one expression or another e.g. Product\*||Order\*
Before interceptor
is called before endpoint is executed.
Before interceptors can used in order to stop the flow
, throw an exception
or enrich the
Message.
We will intercept Command Handler with verification if executor is an administrator.Attribute
called IsAdministrator
in new namepace.Before Interceptor.
#[RequireAdministrator]
annotation in each of registered Endpoints.
The void return type
is expected in here. It tells Ecotone
that, this Before Interceptor is not modifying the Message and message will be passed through. The message flow however can be interrupted by throwing exception.Command Handler
is using ChangePriceCommand
class and our AdminVerificator interceptor
is using array $payload
. They are both the same payload of the Message, but converted in the way Endpoint expected. not void
new modified based on previous Message will be created from the returned type.
We will enrich Message payload with timestamp.not void
new modified based on previous Message will be created from the returned type. If we additionally add changeHeaders: true
it will tell Ecotone, that we we want to modify Message headers instead of payload. Message Filter
, to eliminate undesired messages based on a set of criteria.
This can be done by returning null from interceptor, if the flow should proceed, then payload should be returned.not void
new modified based on previous Message will be created from the returned type. If we additionally add changeHeaders=true
it will tell Ecotone, that we we want to modify Message headers instead of payload. Around Interceptor
have access to actual Method Invocation.
This does allow for starting some procedure and ending after the invocation is done. At this moment all conversions are done, so we can't convert payload to different type. Around interceptor
is a good place for handling transactions or logic shared between different endpoints, that need to access invoked object. Command Bus
interface as pointcut, we told Ecotone
that it should intercept Command Bus Gateway.
Now whenever we will call any method on Command Bus, it will be intercepted with transaction.
The other powerful use case for Around Interceptor is intercepting Aggregate.
Suppose we want to verify, if executing user has access to the Aggregate.@IsOwnerOfPerson
annotation as the top of class. For interceptor pointcut it means, that each endpoint defined in this class should be intercepted. No need to add it on each Command Handler now.After interceptor
is called after endpoint execution has finished.
It does work exactly the same as Before Interceptor.
After interceptor can used to for example to enrich QueryHandler
result.result
key.Presend Interceptor
is called before Message is actually send to the channel.
In synchronous channel there is no difference between Before
and Presend.
The difference is seen when the channel is asynchronous.Presend Interceptor
can be used for example, when Command Bus is called from HTTP Controller.
Then we may want to verify if data is correct and if not filter out the Message, or we may want to check, if user has enough permissions to do the action or validate payload.
This will keep our asynchronous channel free of incorrect messages.