GH-9617: @SuppressWarnings("removal") for ListenableFuture
Fixes: #9617 Issue link: https://github.com/spring-projects/spring-integration/issues/9617 The `ListenableFuture` is marked `forRemoval` in Spring Framework. So, fix the code base to use `@SuppressWarnings("removal")`. Also, add a warning into logs that `ListenableFuture` support will be removed in `7.0`. * Fix JavaDocs where `ListenableFuture` is mentioned in favor of `CompletableFuture`
This commit is contained in:
@@ -114,7 +114,7 @@ ext {
|
||||
springKafkaVersion = '3.3.0-SNAPSHOT'
|
||||
springRetryVersion = '2.0.10'
|
||||
springSecurityVersion = '6.4.0-SNAPSHOT'
|
||||
springVersion = '6.2.0-RC2'
|
||||
springVersion = '6.2.0-SNAPSHOT'
|
||||
springWsVersion = '4.0.11'
|
||||
testcontainersVersion = '1.20.3'
|
||||
tomcatVersion = '10.1.31'
|
||||
|
||||
@@ -363,9 +363,9 @@ public class GatewayProxyFactoryBean<T> extends AbstractEndpoint
|
||||
|
||||
/**
|
||||
* Set the executor for use when the gateway method returns
|
||||
* {@link java.util.concurrent.Future} or {@link org.springframework.util.concurrent.ListenableFuture}.
|
||||
* {@link Future} or {@link CompletableFuture}.
|
||||
* Set it to null to disable the async processing, and any
|
||||
* {@link java.util.concurrent.Future} return types must be returned by the downstream flow.
|
||||
* {@link Future} return types must be returned by the downstream flow.
|
||||
* @param executor The executor.
|
||||
*/
|
||||
public void setAsyncExecutor(@Nullable Executor executor) {
|
||||
@@ -522,7 +522,7 @@ public class GatewayProxyFactoryBean<T> extends AbstractEndpoint
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
@SuppressWarnings("deprecation")
|
||||
@SuppressWarnings("removal")
|
||||
public Object invoke(final MethodInvocation invocation) throws Throwable { // NOSONAR
|
||||
Method method = invocation.getMethod();
|
||||
Class<?> returnType;
|
||||
@@ -542,6 +542,9 @@ public class GatewayProxyFactoryBean<T> extends AbstractEndpoint
|
||||
return CompletableFuture.supplyAsync(invoker, this.asyncExecutor);
|
||||
}
|
||||
else if (org.springframework.util.concurrent.ListenableFuture.class.equals(returnType)) {
|
||||
logger.warn("The 'org.springframework.util.concurrent.ListenableFuture' is deprecated for removal." +
|
||||
"The 'CompletableFuture' is recommended to be used instead." +
|
||||
"The 'ListenableFuture' support will be removed in Spring Integration 7.0.");
|
||||
return ((org.springframework.core.task.AsyncListenableTaskExecutor) this.asyncExecutor)
|
||||
.submitListenable(invoker::get);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Marius Bogoevici
|
||||
* @author Ngoc Nhan
|
||||
*
|
||||
* since 4.1
|
||||
* @since 4.1
|
||||
*/
|
||||
public abstract class AbstractMessageProducingHandler extends AbstractMessageHandler
|
||||
implements MessageProducer, HeaderPropagationAware {
|
||||
@@ -321,7 +321,7 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
return replyChannel;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@SuppressWarnings("removal")
|
||||
private void doProduceOutput(Message<?> requestMessage, MessageHeaders requestHeaders, Object reply,
|
||||
@Nullable Object replyChannelArg) {
|
||||
|
||||
@@ -361,7 +361,7 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
sendOutput(createOutputMessage(reply, requestHeaders), replyChannel, false);
|
||||
}
|
||||
|
||||
private static Publisher<?> toPublisherReply(Object reply, @Nullable ReactiveAdapter reactiveAdapter) {
|
||||
private Publisher<?> toPublisherReply(Object reply, @Nullable ReactiveAdapter reactiveAdapter) {
|
||||
if (reactiveAdapter != null) {
|
||||
return reactiveAdapter.toPublisher(reply);
|
||||
}
|
||||
@@ -371,7 +371,7 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
private static CompletableFuture<?> toFutureReply(Object reply, @Nullable ReactiveAdapter reactiveAdapter) {
|
||||
private CompletableFuture<?> toFutureReply(Object reply, @Nullable ReactiveAdapter reactiveAdapter) {
|
||||
if (reactiveAdapter != null) {
|
||||
Mono<?> reactiveReply;
|
||||
Publisher<?> publisher = reactiveAdapter.toPublisher(reply);
|
||||
@@ -419,12 +419,15 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static CompletableFuture<?> toCompletableFuture(Object reply) {
|
||||
if (reply instanceof CompletableFuture<?>) {
|
||||
return (CompletableFuture<?>) reply;
|
||||
@SuppressWarnings("removal")
|
||||
private CompletableFuture<?> toCompletableFuture(Object reply) {
|
||||
if (reply instanceof CompletableFuture<?> completableFuture) {
|
||||
return completableFuture;
|
||||
}
|
||||
else {
|
||||
logger.warn("The 'org.springframework.util.concurrent.ListenableFuture' is deprecated for removal." +
|
||||
"The 'CompletableFuture' is recommended to be used instead." +
|
||||
"The 'ListenableFuture' support will be removed in Spring Integration 7.0.");
|
||||
return ((org.springframework.util.concurrent.ListenableFuture<?>) reply).completable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,14 +444,6 @@ public class GatewayInterfaceTests {
|
||||
assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(result2.get().getName()).startsWith("exec-");
|
||||
|
||||
org.springframework.util.concurrent.ListenableFuture<Thread> result3 =
|
||||
this.execGateway.test3(Thread.currentThread());
|
||||
final CountDownLatch latch1 = new CountDownLatch(1);
|
||||
result3.addCallback(data -> latch1.countDown(), ex -> {
|
||||
});
|
||||
assertThat(latch1.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(result3.get().getName()).startsWith("exec-");
|
||||
|
||||
/*
|
||||
@IntegrationComponentScan(useDefaultFilters = false,
|
||||
includeFilters = @ComponentScan.Filter(TestMessagingGateway.class))
|
||||
@@ -770,10 +762,6 @@ public class GatewayInterfaceTests {
|
||||
@Gateway(requestChannel = "gatewayThreadChannel")
|
||||
CompletableFuture<Thread> test2(Thread caller);
|
||||
|
||||
@Gateway(requestChannel = "gatewayThreadChannel")
|
||||
@SuppressWarnings("deprecation")
|
||||
org.springframework.util.concurrent.ListenableFuture<Thread> test3(Thread caller);
|
||||
|
||||
}
|
||||
|
||||
@MessagingGateway(name = "noExecutorGateway", asyncExecutor = AnnotationConstants.NULL)
|
||||
|
||||
@@ -50,18 +50,18 @@ import org.springframework.util.MimeType;
|
||||
* <p>
|
||||
* An RSocket operation is determined by the configured {@link RSocketInteractionModel} or respective SpEL
|
||||
* expression to be evaluated at runtime against the request message.
|
||||
* By default the {@link RSocketInteractionModel#requestResponse} operation is used.
|
||||
* By default, the {@link RSocketInteractionModel#requestResponse} operation is used.
|
||||
* <p>
|
||||
* For a {@link Publisher}-based requests, it must be present in the request message {@code payload}.
|
||||
* The flattening via upstream {@link org.springframework.integration.channel.FluxMessageChannel} will work, too,
|
||||
* but this way we will lose a scope of particular request and every {@link Publisher} event
|
||||
* will be send in its own plain request.
|
||||
* will be sent in its own plain request.
|
||||
* <p>
|
||||
* If reply is a {@link reactor.core.publisher.Flux}, it is wrapped to the {@link Mono} to retain a request scope.
|
||||
* The downstream flow is responsible to obtain this {@link reactor.core.publisher.Flux} from a message payload
|
||||
* and subscribe to it by itself. The {@link Mono} reply from this component is subscribed from the downstream
|
||||
* {@link org.springframework.integration.channel.FluxMessageChannel} or it is adapted to the
|
||||
* {@link org.springframework.util.concurrent.ListenableFuture} otherwise.
|
||||
* {@link java.util.concurrent.CompletableFuture} otherwise.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
*
|
||||
|
||||
@@ -49,11 +49,10 @@ import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Base {@link StompSessionManager} implementation to manage a single {@link StompSession}
|
||||
* over its {@link ListenableFuture} from the target implementation of this class.
|
||||
* over its {@link CompletableFuture} from the target implementation of this class.
|
||||
* <p>
|
||||
* The connection to the {@link StompSession} is made during {@link #start()}.
|
||||
* <p>
|
||||
|
||||
@@ -618,9 +618,6 @@ 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]]
|
||||
==== Usage Scenarios
|
||||
|
||||
|
||||
Reference in New Issue
Block a user