Skip to content

Commit e85afff

Browse files
committed
Merge branch '6.2.x'
2 parents 9daf99a + ba39385 commit e85afff

File tree

2 files changed

+38
-12
lines changed

2 files changed

+38
-12
lines changed

spring-web/src/main/java/org/springframework/http/client/ReactorClientHttpRequest.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,15 @@
2020
import java.io.UncheckedIOException;
2121
import java.net.URI;
2222
import java.time.Duration;
23-
import java.util.Objects;
2423
import java.util.concurrent.Executor;
25-
import java.util.concurrent.atomic.AtomicReference;
2624

2725
import io.netty.buffer.ByteBuf;
2826
import io.netty.buffer.ByteBufAllocator;
2927
import org.jspecify.annotations.Nullable;
3028
import org.reactivestreams.FlowAdapters;
3129
import org.reactivestreams.Publisher;
3230
import reactor.core.publisher.Mono;
31+
import reactor.core.scheduler.Schedulers;
3332
import reactor.netty.NettyOutbound;
3433
import reactor.netty.http.client.HttpClient;
3534
import reactor.netty.http.client.HttpClientRequest;
@@ -44,6 +43,7 @@
4443
*
4544
* @author Arjen Poutsma
4645
* @author Juergen Hoeller
46+
* @author Brian Clozel
4747
* @since 6.1
4848
*/
4949
final class ReactorClientHttpRequest extends AbstractStreamingClientHttpRequest {
@@ -54,6 +54,8 @@ final class ReactorClientHttpRequest extends AbstractStreamingClientHttpRequest
5454

5555
private final URI uri;
5656

57+
private final Executor executor;
58+
5759
private final @Nullable Duration exchangeTimeout;
5860

5961

@@ -65,19 +67,31 @@ final class ReactorClientHttpRequest extends AbstractStreamingClientHttpRequest
6567
* @since 6.2
6668
*/
6769
public ReactorClientHttpRequest(HttpClient httpClient, HttpMethod method, URI uri) {
68-
this.httpClient = httpClient;
69-
this.method = method;
70-
this.uri = uri;
71-
this.exchangeTimeout = null;
70+
this(httpClient, method, uri, null);
71+
}
72+
73+
/**
74+
* Create an instance.
75+
* <p>If no executor is provided, the request will use an {@link Schedulers#boundedElastic() elastic scheduler}
76+
* for performing blocking I/O operations.
77+
* @param httpClient the client to perform the request with
78+
* @param executor the executor to use
79+
* @param method the HTTP method
80+
* @param uri the URI for the request
81+
* @since 6.2.13
82+
*/
83+
public ReactorClientHttpRequest(HttpClient httpClient, HttpMethod method, URI uri, @Nullable Executor executor) {
84+
this(httpClient, method, uri, executor, null);
7285
}
7386

7487
/**
7588
* Package private constructor for use until exchangeTimeout is removed.
7689
*/
77-
ReactorClientHttpRequest(HttpClient httpClient, HttpMethod method, URI uri, @Nullable Duration exchangeTimeout) {
90+
ReactorClientHttpRequest(HttpClient httpClient, HttpMethod method, URI uri, @Nullable Executor executor, @Nullable Duration exchangeTimeout) {
7891
this.httpClient = httpClient;
7992
this.method = method;
8093
this.uri = uri;
94+
this.executor = (executor != null) ? executor : Schedulers.boundedElastic()::schedule;
8195
this.exchangeTimeout = exchangeTimeout;
8296
}
8397

@@ -132,13 +146,10 @@ private Publisher<Void> send(
132146
return Mono.empty();
133147
}
134148

135-
AtomicReference<@Nullable Executor> executorRef = new AtomicReference<>();
136-
137149
return outbound
138-
.withConnection(connection -> executorRef.set(connection.channel().eventLoop()))
139150
.send(FlowAdapters.toPublisher(new OutputStreamPublisher<>(
140151
os -> body.writeTo(StreamUtils.nonClosing(os)), new ByteBufMapper(outbound),
141-
Objects.requireNonNull(executorRef.getAndSet(null)), null)));
152+
this.executor, null)));
142153
}
143154

144155
static IOException convertException(RuntimeException ex) {

spring-web/src/main/java/org/springframework/http/client/ReactorClientHttpRequestFactory.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
import java.io.IOException;
2020
import java.net.URI;
2121
import java.time.Duration;
22+
import java.util.concurrent.Executor;
2223
import java.util.function.Function;
2324

2425
import io.netty.channel.ChannelOption;
2526
import org.apache.commons.logging.Log;
2627
import org.apache.commons.logging.LogFactory;
2728
import org.jspecify.annotations.Nullable;
29+
import reactor.core.scheduler.Schedulers;
2830
import reactor.netty.http.client.HttpClient;
2931
import reactor.netty.resources.ConnectionProvider;
3032
import reactor.netty.resources.LoopResources;
@@ -42,6 +44,7 @@
4244
* @author Arjen Poutsma
4345
* @author Juergen Hoeller
4446
* @author Sebastien Deleuze
47+
* @author Brian Clozel
4548
* @since 6.2
4649
*/
4750
public class ReactorClientHttpRequestFactory implements ClientHttpRequestFactory, SmartLifecycle {
@@ -58,6 +61,8 @@ public class ReactorClientHttpRequestFactory implements ClientHttpRequestFactory
5861

5962
private final @Nullable Function<HttpClient, HttpClient> mapper;
6063

64+
private @Nullable Executor executor;
65+
6166
private @Nullable Integer connectTimeout;
6267

6368
private @Nullable Duration readTimeout;
@@ -126,6 +131,16 @@ private HttpClient createHttpClient(ReactorResourceFactory factory, Function<Htt
126131
return client;
127132
}
128133

134+
/**
135+
* Set the {@code Executor} to use for performing blocking I/O operations.
136+
* <p>If no executor is provided, the request will use an {@link Schedulers#boundedElastic() elastic scheduler}.
137+
* @param executor the executor to use.
138+
* @since 6.2.13
139+
*/
140+
public void setExecutor(Executor executor) {
141+
Assert.notNull(executor, "Executor must not be null");
142+
this.executor = executor;
143+
}
129144

130145
/**
131146
* Set the connect timeout value on the underlying client.
@@ -186,7 +201,7 @@ public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IO
186201
"Expected HttpClient or ResourceFactory and mapper");
187202
client = createHttpClient(this.resourceFactory, this.mapper);
188203
}
189-
return new ReactorClientHttpRequest(client, httpMethod, uri, this.exchangeTimeout);
204+
return new ReactorClientHttpRequest(client, httpMethod, uri, this.executor, this.exchangeTimeout);
190205
}
191206

192207

0 commit comments

Comments
 (0)