GH-10018: Implement async for Java DSL gateway()

Fixes: https://github.com/spring-projects/spring-integration/issues/10018

The `GatewayEndpointSpec` configuration of the `gateway()` operator support already an `async(true)` option.
However, it is silently ignored internally since no real async contract provided for the gateway proxy.

* Introduce the `AsyncRequestReplyExchanger` interface to use instead of `RequestReplyExchanger`,
when  `gateway()` operator is opted-in for the `async(true)`
* Use this new `AsyncRequestReplyExchanger` in the `GatewayMessageHandler` when `async(true)`
* Also, expose a `GatewayEndpointSpec.asyncExecutor(Executor)` option to support async behavior similar to the `@MessagingGateway`
This commit is contained in:
Artem Bilan
2025-05-12 16:18:29 -04:00
parent 53cccd0b25
commit bd4e041185
8 changed files with 158 additions and 28 deletions

View File

@@ -34,3 +34,6 @@ private static IntegrationFlow subFlow() {
IMPORTANT: If the downstream flow does not always return a reply, you should set the `requestTimeout` to 0 to prevent hanging the calling thread indefinitely.
In that case, the flow will end at that point and the thread released for further work.
Starting with version 6.5, this `gateway()` operator fully supports an `async(true)` behaviour.
Internally, an `AsyncRequestReplyExchanger` service interface is provided for the `GatewayProxyFactoryBean`.
And since `AsyncRequestReplyExchanger` contract is a `CompletableFuture<Message<?>>`, the whole request-reply is executed in asynchronous manner.

View File

@@ -560,6 +560,12 @@ 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.
Also, starting with version 6.5, the Java DSL `gateway()` operator fully supports an `async(true)` behaviour.
Internally, an `AsyncRequestReplyExchanger` service interface is provided for the `GatewayProxyFactoryBean`.
And since `AsyncRequestReplyExchanger` contract is a `CompletableFuture<Message<?>>`, the whole request-reply is executed in asynchronous manner.
This behavior is useful, for example, in case of splitter-aggregator scenario when another flow has to be called for each item.
However, the order is not important - only their group gathering on the aggregator after all processing.
[[gateway-asynctaskexecutor]]
=== `AsyncTaskExecutor`

View File

@@ -31,6 +31,9 @@ The `AbstractMessageChannel` beans now throw a special `MessageDispatchingExcept
In general, it is a design error to try to produce a message from `afterPropertiesSet()`, `@PostConstruct` or bean definition methods.
The `SmartLifecycle.start()` is preferred way for this kind of logic, or better to do that via inbound channel adapters.
The Java DSL `gateway()` operator now fully supports an `async(true)` behavior.
See xref:gateway.adoc[] for more information.
[[x6.5-lock-request-handler-advice]]
== The `LockRequestHandlerAdvice`