diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/io/rest-client.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/io/rest-client.adoc
index b371623f77..84eff6c87e 100644
--- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/io/rest-client.adoc
+++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/io/rest-client.adoc
@@ -181,8 +181,8 @@ Spring Boot will auto-detect which HTTP client to use with `RestClient` and `Res
In order of preference, the following clients are supported:
. Apache HttpClient
-. OkHttp
. Jetty HttpClient
+. OkHttp (deprecated)
. Simple JDK client (`HttpURLConnection`)
If multiple clients are available on the classpath, the most preferred client will be used.
diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java
index 53cb7b8366..11b9b881af 100644
--- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java
+++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java
@@ -38,7 +38,7 @@ import org.springframework.http.RequestEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
-import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
+import org.springframework.http.client.JettyClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.mock.http.client.MockClientHttpRequest;
@@ -86,15 +86,16 @@ class TestRestTemplateTests {
@Test
void doNotReplaceCustomRequestFactory() {
- RestTemplateBuilder builder = new RestTemplateBuilder().requestFactory(OkHttp3ClientHttpRequestFactory.class);
+ RestTemplateBuilder builder = new RestTemplateBuilder()
+ .requestFactory(HttpComponentsClientHttpRequestFactory.class);
TestRestTemplate testRestTemplate = new TestRestTemplate(builder);
assertThat(testRestTemplate.getRestTemplate().getRequestFactory())
- .isInstanceOf(OkHttp3ClientHttpRequestFactory.class);
+ .isInstanceOf(HttpComponentsClientHttpRequestFactory.class);
}
@Test
void useTheSameRequestFactoryClassWithBasicAuth() {
- OkHttp3ClientHttpRequestFactory customFactory = new OkHttp3ClientHttpRequestFactory();
+ JettyClientHttpRequestFactory customFactory = new JettyClientHttpRequestFactory();
RestTemplateBuilder builder = new RestTemplateBuilder().requestFactory(() -> customFactory);
TestRestTemplate testRestTemplate = new TestRestTemplate(builder).withBasicAuth("test", "test");
RestTemplate restTemplate = testRestTemplate.getRestTemplate();
diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java
index 93e4e407c8..0ecdc850a0 100644
--- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java
+++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java
@@ -89,24 +89,25 @@ public final class ClientHttpRequestFactories {
* dependencies {@link ClassUtils#isPresent are available} is returned:
*
* - {@link HttpComponentsClientHttpRequestFactory}
- * - {@link OkHttp3ClientHttpRequestFactory}
* - {@link JettyClientHttpRequestFactory}
+ * - {@link OkHttp3ClientHttpRequestFactory} (deprecated)
* - {@link SimpleClientHttpRequestFactory}
*
* @param settings the settings to apply
* @return a new {@link ClientHttpRequestFactory}
*/
+ @SuppressWarnings("removal")
public static ClientHttpRequestFactory get(ClientHttpRequestFactorySettings settings) {
Assert.notNull(settings, "Settings must not be null");
if (APACHE_HTTP_CLIENT_PRESENT) {
return HttpComponents.get(settings);
}
- if (OKHTTP_CLIENT_PRESENT) {
- return OkHttp.get(settings);
- }
if (JETTY_CLIENT_PRESENT) {
return Jetty.get(settings);
}
+ if (OKHTTP_CLIENT_PRESENT) {
+ return OkHttp.get(settings);
+ }
return Simple.get(settings);
}
@@ -119,7 +120,7 @@ public final class ClientHttpRequestFactories {
* {@link HttpComponentsClientHttpRequestFactory}
* {@link JdkClientHttpRequestFactory}
* {@link JettyClientHttpRequestFactory}
- * {@link OkHttp3ClientHttpRequestFactory}
+ * {@link OkHttp3ClientHttpRequestFactory} (deprecated)
* {@link SimpleClientHttpRequestFactory}
*
* A {@code requestFactoryType} of {@link ClientHttpRequestFactory} is equivalent to
@@ -129,7 +130,7 @@ public final class ClientHttpRequestFactories {
* @param settings the settings to apply
* @return a new {@link ClientHttpRequestFactory} instance
*/
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({ "unchecked", "removal" })
public static T get(Class requestFactoryType,
ClientHttpRequestFactorySettings settings) {
Assert.notNull(settings, "Settings must not be null");
@@ -139,9 +140,6 @@ public final class ClientHttpRequestFactories {
if (requestFactoryType == HttpComponentsClientHttpRequestFactory.class) {
return (T) HttpComponents.get(settings);
}
- if (requestFactoryType == OkHttp3ClientHttpRequestFactory.class) {
- return (T) OkHttp.get(settings);
- }
if (requestFactoryType == JettyClientHttpRequestFactory.class) {
return (T) Jetty.get(settings);
}
@@ -151,6 +149,9 @@ public final class ClientHttpRequestFactories {
if (requestFactoryType == SimpleClientHttpRequestFactory.class) {
return (T) Simple.get(settings);
}
+ if (requestFactoryType == OkHttp3ClientHttpRequestFactory.class) {
+ return (T) OkHttp.get(settings);
+ }
return get(() -> createRequestFactory(requestFactoryType), settings);
}
@@ -220,6 +221,8 @@ public final class ClientHttpRequestFactories {
/**
* Support for {@link OkHttp3ClientHttpRequestFactory}.
*/
+ @Deprecated(since = "3.2.0", forRemoval = true)
+ @SuppressWarnings("removal")
static class OkHttp {
static OkHttp3ClientHttpRequestFactory get(ClientHttpRequestFactorySettings settings) {
diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesRuntimeHints.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesRuntimeHints.java
index 90f3db9af1..45a3744a4b 100644
--- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesRuntimeHints.java
+++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesRuntimeHints.java
@@ -56,10 +56,6 @@ class ClientHttpRequestFactoriesRuntimeHints implements RuntimeHintsRegistrar {
typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.APACHE_HTTP_CLIENT_CLASS));
registerReflectionHints(hints, HttpComponentsClientHttpRequestFactory.class);
});
- hints.registerTypeIfPresent(classLoader, ClientHttpRequestFactories.OKHTTP_CLIENT_CLASS, (typeHint) -> {
- typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.OKHTTP_CLIENT_CLASS));
- registerReflectionHints(hints, OkHttp3ClientHttpRequestFactory.class);
- });
hints.registerTypeIfPresent(classLoader, ClientHttpRequestFactories.JETTY_CLIENT_CLASS, (typeHint) -> {
typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.JETTY_CLIENT_CLASS));
registerReflectionHints(hints, JettyClientHttpRequestFactory.class, long.class);
@@ -68,6 +64,17 @@ class ClientHttpRequestFactoriesRuntimeHints implements RuntimeHintsRegistrar {
typeHint.onReachableType(HttpURLConnection.class);
registerReflectionHints(hints, SimpleClientHttpRequestFactory.class);
});
+ registerOkHttpHints(hints, classLoader);
+ }
+
+ @SuppressWarnings("removal")
+ @Deprecated(since = "3.2.0", forRemoval = true)
+ private void registerOkHttpHints(ReflectionHints hints, ClassLoader classLoader) {
+ hints.registerTypeIfPresent(classLoader, ClientHttpRequestFactories.OKHTTP_CLIENT_CLASS, (typeHint) -> {
+ typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.OKHTTP_CLIENT_CLASS));
+ registerReflectionHints(hints, OkHttp3ClientHttpRequestFactory.class);
+ });
+
}
private void registerReflectionHints(ReflectionHints hints,
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesOkHttp3Tests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesOkHttp3Tests.java
index b54e8050d2..ad414d38f2 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesOkHttp3Tests.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesOkHttp3Tests.java
@@ -35,7 +35,9 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Andy Wilkinson
*/
@ClassPathOverrides("com.squareup.okhttp3:okhttp:3.14.9")
-@ClassPathExclusions("httpclient5-*.jar")
+@ClassPathExclusions({ "httpclient5-*.jar", "jetty-client-*.jar" })
+@Deprecated(since = "3.2.0")
+@SuppressWarnings("removal")
class ClientHttpRequestFactoriesOkHttp3Tests
extends AbstractClientHttpRequestFactoriesTests {
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesOkHttp4Tests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesOkHttp4Tests.java
index d1f533f731..f6241c7a41 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesOkHttp4Tests.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesOkHttp4Tests.java
@@ -33,7 +33,9 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Andy Wilkinson
*/
-@ClassPathExclusions("httpclient5-*.jar")
+@ClassPathExclusions({ "httpclient5-*.jar", "jetty-client-*.jar" })
+@Deprecated(since = "3.2.0")
+@SuppressWarnings("removal")
class ClientHttpRequestFactoriesOkHttp4Tests
extends AbstractClientHttpRequestFactoriesTests {
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesRuntimeHintsTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesRuntimeHintsTests.java
index 7eee323f11..1fc41a8e29 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesRuntimeHintsTests.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesRuntimeHintsTests.java
@@ -63,6 +63,8 @@ class ClientHttpRequestFactoriesRuntimeHintsTests {
}
@Test
+ @Deprecated(since = "3.2.0")
+ @SuppressWarnings("removal")
void shouldRegisterOkHttpHints() {
RuntimeHints hints = new RuntimeHints();
new ClientHttpRequestFactoriesRuntimeHints().registerHints(hints, getClass().getClassLoader());
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesTests.java
index 239023e8b9..ff27a20d03 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesTests.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesTests.java
@@ -70,6 +70,8 @@ class ClientHttpRequestFactoriesTests {
}
@Test
+ @Deprecated(since = "3.2.0")
+ @SuppressWarnings("removal")
void getOfOkHttpFactoryReturnsOkHttpFactory() {
ClientHttpRequestFactory requestFactory = ClientHttpRequestFactories.get(OkHttp3ClientHttpRequestFactory.class,
ClientHttpRequestFactorySettings.DEFAULTS);
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/webservices/client/HttpWebServiceMessageSenderBuilderOkHttp3IntegrationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/webservices/client/HttpWebServiceMessageSenderBuilderOkHttp3IntegrationTests.java
index e48feb9be0..3215dad499 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/webservices/client/HttpWebServiceMessageSenderBuilderOkHttp3IntegrationTests.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/webservices/client/HttpWebServiceMessageSenderBuilderOkHttp3IntegrationTests.java
@@ -18,12 +18,12 @@ package org.springframework.boot.webservices.client;
import java.time.Duration;
-import okhttp3.OkHttpClient;
+import org.eclipse.jetty.client.HttpClient;
import org.junit.jupiter.api.Test;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.http.client.ClientHttpRequestFactory;
-import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
+import org.springframework.http.client.JettyClientHttpRequestFactory;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.ws.transport.http.ClientHttpRequestMessageSender;
@@ -42,9 +42,9 @@ class HttpWebServiceMessageSenderBuilderOkHttp3IntegrationTests {
private final HttpWebServiceMessageSenderBuilder builder = new HttpWebServiceMessageSenderBuilder();
@Test
- void buildUseOkHttp3ByDefault() {
+ void buildUseJettyClientIfHttpComponentsIsNotAvailable() {
WebServiceMessageSender messageSender = this.builder.build();
- assertOkHttp3RequestFactory(messageSender);
+ assertJettyClientHttpRequestFactory(messageSender);
}
@Test
@@ -52,19 +52,19 @@ class HttpWebServiceMessageSenderBuilderOkHttp3IntegrationTests {
WebServiceMessageSender messageSender = this.builder.setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(2))
.build();
- OkHttp3ClientHttpRequestFactory factory = assertOkHttp3RequestFactory(messageSender);
- OkHttpClient client = (OkHttpClient) ReflectionTestUtils.getField(factory, "client");
+ JettyClientHttpRequestFactory factory = assertJettyClientHttpRequestFactory(messageSender);
+ HttpClient client = (HttpClient) ReflectionTestUtils.getField(factory, "httpClient");
assertThat(client).isNotNull();
- assertThat(client.connectTimeoutMillis()).isEqualTo(5000);
- assertThat(client.readTimeoutMillis()).isEqualTo(2000);
+ assertThat(client.getConnectTimeout()).isEqualTo(5000);
+ assertThat(factory).hasFieldOrPropertyWithValue("readTimeout", 2000L);
}
- private OkHttp3ClientHttpRequestFactory assertOkHttp3RequestFactory(WebServiceMessageSender messageSender) {
+ private JettyClientHttpRequestFactory assertJettyClientHttpRequestFactory(WebServiceMessageSender messageSender) {
assertThat(messageSender).isInstanceOf(ClientHttpRequestMessageSender.class);
ClientHttpRequestMessageSender sender = (ClientHttpRequestMessageSender) messageSender;
ClientHttpRequestFactory requestFactory = sender.getRequestFactory();
- assertThat(requestFactory).isInstanceOf(OkHttp3ClientHttpRequestFactory.class);
- return (OkHttp3ClientHttpRequestFactory) requestFactory;
+ assertThat(requestFactory).isInstanceOf(JettyClientHttpRequestFactory.class);
+ return (JettyClientHttpRequestFactory) requestFactory;
}
}
diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-couchbase/build.gradle b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-couchbase/build.gradle
index e66d4db03d..fba550646e 100644
--- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-couchbase/build.gradle
+++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-couchbase/build.gradle
@@ -13,9 +13,9 @@ dependencies {
testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
testImplementation(project(":spring-boot-project:spring-boot-testcontainers"))
- testImplementation("com.squareup.okhttp3:okhttp")
testImplementation("io.projectreactor:reactor-core")
testImplementation("io.projectreactor:reactor-test")
+ testImplementation("org.apache.httpcomponents.client5:httpclient5")
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("org.junit.platform:junit-platform-engine")
testImplementation("org.junit.platform:junit-platform-launcher")
diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-couchbase/src/test/java/smoketest/data/couchbase/SecureCouchbaseContainer.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-couchbase/src/test/java/smoketest/data/couchbase/SecureCouchbaseContainer.java
index 1b40442edc..70141b4540 100644
--- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-couchbase/src/test/java/smoketest/data/couchbase/SecureCouchbaseContainer.java
+++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-couchbase/src/test/java/smoketest/data/couchbase/SecureCouchbaseContainer.java
@@ -17,13 +17,14 @@
package smoketest.data.couchbase;
import java.time.Duration;
+import java.util.Base64;
import com.github.dockerjava.api.command.InspectContainerResponse;
-import okhttp3.Credentials;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.RequestBody;
-import okhttp3.Response;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
import org.testcontainers.couchbase.CouchbaseContainer;
import org.testcontainers.utility.MountableFile;
@@ -33,6 +34,7 @@ import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
* A {@link CouchbaseContainer} for Couchbase with SSL configuration.
*
* @author Scott Frederick
+ * @author Stephane Nicoll
*/
public class SecureCouchbaseContainer extends CouchbaseContainer {
@@ -69,20 +71,26 @@ public class SecureCouchbaseContainer extends CouchbaseContainer {
}
private void doHttpRequest(String path) {
- Response response;
- try {
+ HttpResponse response = post(path);
+ if (response.getCode() != 200) {
+ throw new IllegalStateException("Error calling Couchbase HTTP endpoint: " + response);
+ }
+ }
+
+ private HttpResponse post(String path) {
+ try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
+ String basicAuth = "Basic "
+ + Base64.getEncoder().encodeToString("%s:%s".formatted(ADMIN_USER, ADMIN_PASSWORD).getBytes());
String url = "http://%s:%d/%s".formatted(getHost(), getMappedPort(MANAGEMENT_PORT), path);
- Request.Builder requestBuilder = new Request.Builder().url(url)
- .header("Authorization", Credentials.basic(ADMIN_USER, ADMIN_PASSWORD))
- .post(RequestBody.create("".getBytes()));
- response = new OkHttpClient().newCall(requestBuilder.build()).execute();
+ ClassicHttpRequest httpPost = ClassicRequestBuilder.post(url)
+ .addHeader("Authorization", basicAuth)
+ .setEntity("")
+ .build();
+ return httpclient.execute(httpPost, (response) -> response);
}
catch (Exception ex) {
throw new IllegalStateException("Error calling Couchbase HTTP endpoint", ex);
}
- if (!response.isSuccessful()) {
- throw new IllegalStateException("Error calling Couchbase HTTP endpoint: " + response);
- }
}
}