Fix deprecations around ListenableFuture (#3865)

* Fix deprecations around ListenableFuture

SF has deprecated a `ListenableFuture` and API around it

* Migrate to `CompletableFuture` everywhere a `ListenableFuture` has been used
* Suppress a deprecation for `ListenableFuture` keeping the functionality until the next version
* Resolve deprecations nad removals from the latest Spring for Apache Kafka
* Fix documentation for the `ListenableFuture` in favor of `CompletableFuture`

NOTE: the AMQP module is left as is until `ListenableFuture` deprecation is resolved in Spring AMQP

* * Restore some `ListenableFuture` test for messaging gateway
This commit is contained in:
Artem Bilan
2022-07-28 09:32:01 -04:00
committed by GitHub
parent 2e9beada0b
commit 5572c2161d
23 changed files with 196 additions and 259 deletions

View File

@@ -583,39 +583,13 @@ int finalResult = result.get(1000, TimeUnit.SECONDS);
For a more detailed example, see the https://github.com/spring-projects/spring-integration-samples/tree/main/intermediate/async-gateway[async-gateway] sample in the Spring Integration samples.
===== `ListenableFuture`
Starting with version 4.1, asynchronous gateway methods can also return `ListenableFuture` (introduced in Spring Framework 4.0).
These return types let you provide a callback, which is invoked when the result is available (or an exception occurs).
When the gateway detects this return type and the <<gateway-asynctaskexecutor,task executor>> is an `AsyncListenableTaskExecutor`, the executor's `submitListenable()` method is invoked.
The following example shows how to use a `ListenableFuture`:
====
[source,java]
----
ListenableFuture<String> result = this.asyncGateway.async("something");
result.addCallback(new ListenableFutureCallback<String>() {
@Override
public void onSuccess(String result) {
...
}
@Override
public void onFailure(Throwable t) {
...
}
});
----
====
[[gateway-asynctaskexecutor]]
===== `AsyncTaskExecutor`
By default, the `GatewayProxyFactoryBean` uses `org.springframework.core.task.SimpleAsyncTaskExecutor` when submitting internal `AsyncInvocationTask` instances for any gateway method whose return type is a `Future`.
However, the `async-executor` attribute in the `<gateway/>` element's configuration lets you provide a reference to any implementation of `java.util.concurrent.Executor` available within the Spring application context.
The (default) `SimpleAsyncTaskExecutor` supports both `Future` and `ListenableFuture` return types, returning `FutureTask` or `ListenableFutureTask` respectively.
The (default) `SimpleAsyncTaskExecutor` supports both `Future` and `CompletableFuture` return types.
See <<gw-completable-future>>.
Even though there is a default executor, it is often useful to provide an external one so that you can identify its threads in logs (when using XML, the thread name is based on the executor's bean name), as the following example shows:
@@ -671,6 +645,9 @@ There are two modes of operation when returning this type:
* When the async executor is explicitly set to `null` and the return type is `CompletableFuture` or the return type is a subclass of `CompletableFuture`, the flow is invoked on the caller's thread.
In this scenario, the downstream flow is expected to return a `CompletableFuture` of the appropriate type.
NOTE: The `org.springframework.util.concurrent.ListenableFuture` has been deprecated starting with Spring Framework `6.0`.
It is recommended now to migrate to the `CompletableFuture` which provides similar processing functionality.
====== Usage Scenarios
In the following scenario, the caller thread returns immediately with a `CompletableFuture<Invoice>`, which is completed when the downstream flow replies to the gateway (with an `Invoice` object).
@@ -802,7 +779,7 @@ The calling thread continues, with `handleInvoice()` being called when the flow
===== Downstream Flows Returning an Asynchronous Type
As mentioned in the `ListenableFuture` section above, if you wish some downstream component to return a message with an async payload (`Future`, `Mono`, and others), you must explicitly set the async executor to `null` (or `""` when using XML configuration).
As mentioned in the <<gateway-asynctaskexecutor>> section above, if you wish some downstream component to return a message with an async payload (`Future`, `Mono`, and others), you must explicitly set the async executor to `null` (or `""` when using XML configuration).
The flow is then invoked on the caller thread and the result can be retrieved later.
===== `void` Return Type

View File

@@ -156,9 +156,9 @@ See <<./dsl.adoc#java-dsl-handle,Service Activators and the `.handle()` method>>
The service activator is invoked by the calling thread.
This is an upstream thread if the input channel is a `SubscribableChannel` or a poller thread for a `PollableChannel`.
If the service returns a `ListenableFuture<?>`, the default action is to send that as the payload of the message sent to the output (or reply) channel.
If the service returns a `CompletableFuture<?>`, the default action is to send that as the payload of the message sent to the output (or reply) channel.
Starting with version 4.3, you can now set the `async` attribute to `true` (by using `setAsync(true)` when using Java configuration).
If the service returns a `ListenableFuture<?>` when this the `async` attribute is set to `true`, the calling thread is released immediately and the reply message is sent on the thread (from within your service) that completes the future.
If the service returns a `CompletableFuture<?>` when this the `async` attribute is set to `true`, the calling thread is released immediately and the reply message is sent on the thread (from within your service) that completes the future.
This is particularly advantageous for long-running services that use a `PollableChannel`, because the poller thread is released to perform other services within the framework.
If the service completes the future with an `Exception`, normal error processing occurs.

View File

@@ -52,6 +52,11 @@ The factory class will be removed in the future releases.
See <<./dsl.adoc#java-dsl,Java DSL>> for more information.
The `org.springframework.util.concurrent.ListenableFuture` has been deprecated starting with Spring Framework `6.0`.
All Spring Integration async API has been migrated to the `CompletableFuture`.
See <<./gateway.adoc#gw-completable-future, CompletableFuture support>> for more information.
[[x6.0-http]]
=== HTTP Changes