Introduce a ReceiveMessageAdvice (#3265)

* Introduce a `ReceiveMessageAdvice`

* Deprecate an `AbstractMessageSourceAdvice` in favor of
`default` method in the `MessageSourceMutator`
* Move a `applyReceiveOnlyAdviceChain()` logic into the `AbstractPollingEndpoint`:
now both `PollingConsumer` and `SourcePollingChannelAdapter` can use
`ReceiveMessageAdvice`
* Introduce a `SimpleActiveIdleReceiveMessageAdvice` based already
on the `ReceiveMessageAdvice` and deprecate a `SimpleActiveIdleMessageSourceAdvice`
which is fully replaceable with newly introduced `SimpleActiveIdleReceiveMessageAdvice`
* Add `@SuppressWarnings("deprecation")` for those out-of-the-box `ReceiveMessageAdvice`
implementation which still use an `AbstractMessageSourceAdvice` for
backward compatibility
* Document a new feature and give the `MessageSourceMutator` a new meaning

* * Fix language in the `polling-consumer.adoc`
This commit is contained in:
Artem Bilan
2020-04-28 13:03:30 -04:00
committed by GitHub
parent cfd03f89a0
commit 2d9a5f60f4
16 changed files with 394 additions and 128 deletions

View File

@@ -263,7 +263,7 @@ The following example shows how to declare a delegating session factory:
IMPORTANT: When you use session caching (see <<ftp-session-caching>>), each of the delegates should be cached.
You cannot cache the `DelegatingSessionFactory` itself.
Starting with _version 5.0.7_, the `DelegatingSessionFactory` can be used in conjunction with a `RotatingServerAdvice` to poll multiple servers; see <<ftp-rotating-server-advice>>.
Starting with version 5.0.7, the `DelegatingSessionFactory` can be used in conjunction with a `RotatingServerAdvice` to poll multiple servers; see <<ftp-rotating-server-advice>>.
[[ftp-inbound]]
=== FTP Inbound Channel Adapter
@@ -704,7 +704,7 @@ Notice that, in this example, the message handler downstream of the transformer
[[ftp-rotating-server-advice]]
=== Inbound Channel Adapters: Polling Multiple Servers and Directories
Starting with _version 5.0.7_, the `RotatingServerAdvice` is available; when configured as a poller advice, the inbound adapters can poll multiple servers and directories.
Starting with version 5.0.7, the `RotatingServerAdvice` is available; when configured as a poller advice, the inbound adapters can poll multiple servers and directories.
Configure the advice and add it to the poller's advice chain as normal.
A `DelegatingSessionFactory` is used to select the server see <<ftp-dsf>> for more information.
The advice configuration consists of a list of `RotationPolicy.KeyDirectory` objects.

View File

@@ -145,18 +145,21 @@ These "`around advice`" methods do not have access to any context for the poll -
This is fine for requirements such as making a task transactional or skipping a poll due to some external condition, as discussed earlier.
What if we wish to take some action depending on the result of the `receive` part of the poll or if we want to adjust the poller depending on conditions? For those instances, Spring Integration offers "`Smart`" Polling.
[[smart-polling]]
===== "`Smart`" Polling
Version 4.2 introduced the `AbstractMessageSourceAdvice`.
Any `Advice` objects in the `advice-chain` that subclass this class are applied only to the receive operation.
Version 5.3 introduced the `ReceiveMessageAdvice` interface.
(The `AbstractMessageSourceAdvice` has been deprecated in favor of `default` methods in the `MessageSourceMutator`.)
Any `Advice` objects in the `advice-chain` that implement this interface are applied only to the receive operation - `MessageSource.receive()` and `PollableChannel.receive(timeout)`.
Therefore they can be applied only for the `SourcePollingChannelAdapter` or `PollingConsumer`.
Such classes implement the following methods:
* `beforeReceive(MessageSource<?> source)`
This method is called before the `MessageSource.receive()` method.
* `beforeReceive(Object source)`
This method is called before the `Object.receive()` method.
It lets you examine and reconfigure the source.
Returning `false` cancels this poll (similar to the `PollSkipAdvice` mentioned earlier).
* `Message<?> afterReceive(Message<?> result, MessageSource<?> source)`
* `Message<?> afterReceive(Message<?> result, Object source)`
This method is called after the `receive()` method.
Again, you can reconfigure the source or take any action (perhaps depending on the result, which can be `null` if there was no message created by the source).
You can even return a different message
@@ -164,7 +167,7 @@ You can even return a different message
.Thread safety
[IMPORTANT]
====
If an advice mutates the `MessageSource`, you should not configure the poller with a `TaskExecutor`.
If an advice mutates the the, you should not configure the poller with a `TaskExecutor`.
If an advice mutates the source, such mutations are not thread safe and could cause unexpected results, especially with high frequency pollers.
If you need to process poll results concurrently, consider using a downstream `ExecutorChannel` instead of adding an executor to the poller.
====
@@ -173,21 +176,22 @@ If you need to process poll results concurrently, consider using a downstream `E
[IMPORTANT]
=====
You should understand how the advice chain is processed during initialization.
`Advice` objects that do not extend `AbstractMessageSourceAdvice` are applied to the whole poll process and are all invoked first, in order, before any `AbstractMessageSourceAdvice`.
Then `AbstractMessageSourceAdvice` objects are invoked in order around the `MessageSource` `receive()` method.
If you have, for example, `Advice` objects `a, b, c, d`, where `b` and `d` are `AbstractMessageSourceAdvice`, the objects are applied in the following order: `a, c, b, d`.
Also, if a `MessageSource` is already a `Proxy`, the `AbstractMessageSourceAdvice` is invoked after any existing `Advice` objects.
`Advice` objects that do not implement `ReceiveMessageAdvice` are applied to the whole poll process and are all invoked first, in order, before any `ReceiveMessageAdvice`.
Then `ReceiveMessageAdvice` objects are invoked in order around the source `receive()` method.
If you have, for example, `Advice` objects `a, b, c, d`, where `b` and `d` are `ReceiveMessageAdvice`, the objects are applied in the following order: `a, c, b, d`.
Also, if a source is already a `Proxy`, the `ReceiveMessageAdvice` is invoked after any existing `Advice` objects.
If you wish to change the order, you must wire up the proxy yourself.
=====
===== `SimpleActiveIdleMessageSourceAdvice`
===== `SimpleActiveIdleReceiveMessageAdvice`
This advice is a simple implementation of `AbstractMessageSourceAdvice`.
(The previous `SimpleActiveIdleMessageSourceAdvice` for only `MessageSource` is deprecated.)
This advice is a simple implementation of `ReceiveMessageAdvice`.
When used in conjunction with a `DynamicPeriodicTrigger`, it adjusts the polling frequency, depending on whether or not the previous poll resulted in a message or not.
The poller must also have a reference to the same `DynamicPeriodicTrigger`.
.Important: Async Handoff
IMPORTANT: `SimpleActiveIdleMessageSourceAdvice` modifies the trigger based on the `receive()` result.
IMPORTANT: `SimpleActiveIdleReceiveMessageAdvice` modifies the trigger based on the `receive()` result.
This works only if the advice is called on the poller thread.
It does not work if the poller has a `task-executor`.
To use this advice where you wish to use async operations after the result of a poll, do the async handoff later, perhaps by using an `ExecutorChannel`.
@@ -241,3 +245,10 @@ IMPORTANT: `CompoundTriggerAdvice` modifies the trigger based on the `receive()`
This works only if the advice is called on the poller thread.
It does not work if the poller has a `task-executor`.
To use this advice where you wish to use async operations after the result of a poll, do the async handoff later, perhaps by using an `ExecutorChannel`.
===== MessageSource-only Advices
Some advices might be applied only for the `MessageSource.receive()` and they don't make sense for `PollableChannel`.
For this purpose a `MessageSourceMutator` interface (an extension of the `ReceiveMessageAdvice`) is still present.
With `default` methods it fully replaces already deprecated `AbstractMessageSourceAdvice` and should be used in those implementations where only `MessageSource` proxying is expected.
See <<./ftp.adoc#ftp-rotating-server-advice,Inbound Channel Adapters: Polling Multiple Servers and Directories>> for more information.

View File

@@ -230,7 +230,7 @@ We added convenience methods so that you can more easily do so from a message fl
IMPORTANT: When using session caching (see <<sftp-session-caching>>), each of the delegates should be cached.
You cannot cache the `DelegatingSessionFactory` itself.
Starting with _version 5.0.7_, the `DelegatingSessionFactory` can be used in conjunction with a `RotatingServerAdvice` to poll multiple servers; see <<sftp-rotating-server-advice>>.
Starting with version 5.0.7, the `DelegatingSessionFactory` can be used in conjunction with a `RotatingServerAdvice` to poll multiple servers; see <<sftp-rotating-server-advice>>.
[[sftp-session-caching]]
=== SFTP Session Caching
@@ -703,7 +703,7 @@ Notice that, in this example, the message handler downstream of the transformer
[[sftp-rotating-server-advice]]
=== Inbound Channel Adapters: Polling Multiple Servers and Directories
Starting with _version 5.0.7_, the `RotatingServerAdvice` is available; when configured as a poller advice, the inbound adapters can poll multiple servers and directories.
Starting with version 5.0.7, the `RotatingServerAdvice` is available; when configured as a poller advice, the inbound adapters can poll multiple servers and directories.
Configure the advice and add it to the poller's advice chain as normal.
A `DelegatingSessionFactory` is used to select the server see <<./ftp.adoc#ftp-dsf,Delegating Session Factory>> for more information.
The advice configuration consists of a list of `RotationPolicy.KeyDirectory` objects.

View File

@@ -66,6 +66,12 @@ The `spring-integration-mongodb` module now provides channel adapter implementat
Also, a reactive implementation for MongoDb change stream support is present with the `MongoDbChangeStreamMessageProducer`.
See <<./mongodb.adoc#mongodb,MongoDB Support>> for more information.
[[x5.3-receive-message-advice]]
==== ReceiveMessageAdvice
A special `ReceiveMessageAdvice` has been introduced to proxy exactly `MessageSource.receive()` or `PollableChannel.receive()`.
See <<./polling-consumer.adoc#smart-polling,Smart Polling>> for more information.
[[x5.3-general]]
=== General Changes