Skip to content

Commit 053af5f

Browse files
committed
Merge branch '6.1.x'
2 parents e1567b9 + fea237c commit 053af5f

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

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

+23-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
* @author Brian Clozel
4747
* @author Rossen Stoyanchev
4848
* @author Sebastien Deleuze
49+
* @author Juergen Hoeller
4950
* @since 5.0
5051
* @see reactor.netty.http.client.HttpClient
5152
*/
@@ -72,6 +73,8 @@ public class ReactorClientHttpConnector implements ClientHttpConnector, SmartLif
7273
@Nullable
7374
private volatile HttpClient httpClient;
7475

76+
private boolean lazyStart = false;
77+
7578
private final Object lifecycleMonitor = new Object();
7679

7780

@@ -121,6 +124,9 @@ public ReactorClientHttpConnector(ReactorResourceFactory resourceFactory, Functi
121124
if (resourceFactory.isRunning()) {
122125
this.httpClient = createHttpClient(resourceFactory, mapper);
123126
}
127+
else {
128+
this.lazyStart = true;
129+
}
124130
}
125131

126132
private static HttpClient createHttpClient(ReactorResourceFactory factory, Function<HttpClient, HttpClient> mapper) {
@@ -136,7 +142,21 @@ public Mono<ClientHttpResponse> connect(HttpMethod method, URI uri,
136142
HttpClient httpClient = this.httpClient;
137143
if (httpClient == null) {
138144
Assert.state(this.resourceFactory != null && this.mapper != null, "Illegal configuration");
139-
httpClient = createHttpClient(this.resourceFactory, this.mapper);
145+
if (this.resourceFactory.isRunning()) {
146+
// Retain HttpClient instance if resource factory has been started in the meantime,
147+
// considering this connector instance as lazily started as well.
148+
synchronized (this.lifecycleMonitor) {
149+
httpClient = this.httpClient;
150+
if (httpClient == null && this.lazyStart) {
151+
httpClient = createHttpClient(this.resourceFactory, this.mapper);
152+
this.httpClient = httpClient;
153+
this.lazyStart = false;
154+
}
155+
}
156+
}
157+
if (httpClient == null) {
158+
httpClient = createHttpClient(this.resourceFactory, this.mapper);
159+
}
140160
}
141161

142162
HttpClient.RequestSender requestSender = httpClient
@@ -185,6 +205,7 @@ public void start() {
185205
synchronized (this.lifecycleMonitor) {
186206
if (this.httpClient == null) {
187207
this.httpClient = createHttpClient(this.resourceFactory, this.mapper);
208+
this.lazyStart = false;
188209
}
189210
}
190211
}
@@ -199,6 +220,7 @@ public void stop() {
199220
if (this.resourceFactory != null && this.mapper != null) {
200221
synchronized (this.lifecycleMonitor) {
201222
this.httpClient = null;
223+
this.lazyStart = false;
202224
}
203225
}
204226
}

spring-web/src/test/java/org/springframework/http/client/reactive/ReactorClientHttpConnectorTests.java

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,17 +16,21 @@
1616

1717
package org.springframework.http.client.reactive;
1818

19+
import java.net.URI;
1920
import java.util.function.Function;
2021

2122
import org.junit.jupiter.api.Test;
23+
import reactor.core.publisher.Mono;
2224
import reactor.netty.http.client.HttpClient;
2325

26+
import org.springframework.http.HttpMethod;
2427
import org.springframework.http.client.ReactorResourceFactory;
2528

2629
import static org.assertj.core.api.Assertions.assertThat;
2730

2831
/**
2932
* @author Sebastien Deleuze
33+
* @author Juergen Hoeller
3034
* @since 6.1
3135
*/
3236
class ReactorClientHttpConnectorTests {
@@ -41,6 +45,8 @@ void restartWithDefaultConstructor() {
4145
assertThat(connector.isRunning()).isTrue();
4246
connector.start();
4347
assertThat(connector.isRunning()).isTrue();
48+
connector.stop();
49+
assertThat(connector.isRunning()).isTrue();
4450
}
4551

4652
@Test
@@ -54,6 +60,8 @@ void restartWithHttpClient() {
5460
assertThat(connector.isRunning()).isTrue();
5561
connector.start();
5662
assertThat(connector.isRunning()).isTrue();
63+
connector.stop();
64+
assertThat(connector.isRunning()).isTrue();
5765
}
5866

5967
@Test
@@ -69,6 +77,8 @@ void restartWithExternalResourceFactory() {
6977
assertThat(connector.isRunning()).isFalse();
7078
connector.start();
7179
assertThat(connector.isRunning()).isTrue();
80+
connector.stop();
81+
assertThat(connector.isRunning()).isFalse();
7282
}
7383

7484
@Test
@@ -84,6 +94,27 @@ void lateStartWithExternalResourceFactory() {
8494
assertThat(connector.isRunning()).isFalse();
8595
connector.start();
8696
assertThat(connector.isRunning()).isTrue();
97+
connector.stop();
98+
assertThat(connector.isRunning()).isFalse();
99+
}
100+
101+
@Test
102+
void lazyStartWithExternalResourceFactory() throws Exception {
103+
ReactorResourceFactory resourceFactory = new ReactorResourceFactory();
104+
Function<HttpClient, HttpClient> mapper = Function.identity();
105+
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(resourceFactory, mapper);
106+
assertThat(connector.isRunning()).isFalse();
107+
resourceFactory.start();
108+
connector.connect(HttpMethod.GET, new URI(""), request -> Mono.empty());
109+
assertThat(connector.isRunning()).isTrue();
110+
connector.stop();
111+
assertThat(connector.isRunning()).isFalse();
112+
connector.connect(HttpMethod.GET, new URI(""), request -> Mono.empty());
113+
assertThat(connector.isRunning()).isFalse();
114+
connector.start();
115+
assertThat(connector.isRunning()).isTrue();
116+
connector.stop();
117+
assertThat(connector.isRunning()).isFalse();
87118
}
88119

89120
}

0 commit comments

Comments
 (0)