Deprecate support for OkHttp

Closes gh-36632
pull/36682/head
Stephane Nicoll 1 year ago
parent 19859a9023
commit 191ac10009

@ -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: In order of preference, the following clients are supported:
. Apache HttpClient . Apache HttpClient
. OkHttp
. Jetty HttpClient . Jetty HttpClient
. OkHttp (deprecated)
. Simple JDK client (`HttpURLConnection`) . Simple JDK client (`HttpURLConnection`)
If multiple clients are available on the classpath, the most preferred client will be used. If multiple clients are available on the classpath, the most preferred client will be used.

@ -38,7 +38,7 @@ import org.springframework.http.RequestEntity;
import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 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.http.client.SimpleClientHttpRequestFactory;
import org.springframework.mock.env.MockEnvironment; import org.springframework.mock.env.MockEnvironment;
import org.springframework.mock.http.client.MockClientHttpRequest; import org.springframework.mock.http.client.MockClientHttpRequest;
@ -86,15 +86,16 @@ class TestRestTemplateTests {
@Test @Test
void doNotReplaceCustomRequestFactory() { void doNotReplaceCustomRequestFactory() {
RestTemplateBuilder builder = new RestTemplateBuilder().requestFactory(OkHttp3ClientHttpRequestFactory.class); RestTemplateBuilder builder = new RestTemplateBuilder()
.requestFactory(HttpComponentsClientHttpRequestFactory.class);
TestRestTemplate testRestTemplate = new TestRestTemplate(builder); TestRestTemplate testRestTemplate = new TestRestTemplate(builder);
assertThat(testRestTemplate.getRestTemplate().getRequestFactory()) assertThat(testRestTemplate.getRestTemplate().getRequestFactory())
.isInstanceOf(OkHttp3ClientHttpRequestFactory.class); .isInstanceOf(HttpComponentsClientHttpRequestFactory.class);
} }
@Test @Test
void useTheSameRequestFactoryClassWithBasicAuth() { void useTheSameRequestFactoryClassWithBasicAuth() {
OkHttp3ClientHttpRequestFactory customFactory = new OkHttp3ClientHttpRequestFactory(); JettyClientHttpRequestFactory customFactory = new JettyClientHttpRequestFactory();
RestTemplateBuilder builder = new RestTemplateBuilder().requestFactory(() -> customFactory); RestTemplateBuilder builder = new RestTemplateBuilder().requestFactory(() -> customFactory);
TestRestTemplate testRestTemplate = new TestRestTemplate(builder).withBasicAuth("test", "test"); TestRestTemplate testRestTemplate = new TestRestTemplate(builder).withBasicAuth("test", "test");
RestTemplate restTemplate = testRestTemplate.getRestTemplate(); RestTemplate restTemplate = testRestTemplate.getRestTemplate();

@ -89,24 +89,25 @@ public final class ClientHttpRequestFactories {
* dependencies {@link ClassUtils#isPresent are available} is returned: * dependencies {@link ClassUtils#isPresent are available} is returned:
* <ol> * <ol>
* <li>{@link HttpComponentsClientHttpRequestFactory}</li> * <li>{@link HttpComponentsClientHttpRequestFactory}</li>
* <li>{@link OkHttp3ClientHttpRequestFactory}</li>
* <li>{@link JettyClientHttpRequestFactory}</li> * <li>{@link JettyClientHttpRequestFactory}</li>
* <li>{@link OkHttp3ClientHttpRequestFactory} (deprecated)</li>
* <li>{@link SimpleClientHttpRequestFactory}</li> * <li>{@link SimpleClientHttpRequestFactory}</li>
* </ol> * </ol>
* @param settings the settings to apply * @param settings the settings to apply
* @return a new {@link ClientHttpRequestFactory} * @return a new {@link ClientHttpRequestFactory}
*/ */
@SuppressWarnings("removal")
public static ClientHttpRequestFactory get(ClientHttpRequestFactorySettings settings) { public static ClientHttpRequestFactory get(ClientHttpRequestFactorySettings settings) {
Assert.notNull(settings, "Settings must not be null"); Assert.notNull(settings, "Settings must not be null");
if (APACHE_HTTP_CLIENT_PRESENT) { if (APACHE_HTTP_CLIENT_PRESENT) {
return HttpComponents.get(settings); return HttpComponents.get(settings);
} }
if (OKHTTP_CLIENT_PRESENT) {
return OkHttp.get(settings);
}
if (JETTY_CLIENT_PRESENT) { if (JETTY_CLIENT_PRESENT) {
return Jetty.get(settings); return Jetty.get(settings);
} }
if (OKHTTP_CLIENT_PRESENT) {
return OkHttp.get(settings);
}
return Simple.get(settings); return Simple.get(settings);
} }
@ -119,7 +120,7 @@ public final class ClientHttpRequestFactories {
* <li>{@link HttpComponentsClientHttpRequestFactory}</li> * <li>{@link HttpComponentsClientHttpRequestFactory}</li>
* <li>{@link JdkClientHttpRequestFactory}</li> * <li>{@link JdkClientHttpRequestFactory}</li>
* <li>{@link JettyClientHttpRequestFactory}</li> * <li>{@link JettyClientHttpRequestFactory}</li>
* <li>{@link OkHttp3ClientHttpRequestFactory}</li> * <li>{@link OkHttp3ClientHttpRequestFactory} (deprecated)</li>
* <li>{@link SimpleClientHttpRequestFactory}</li> * <li>{@link SimpleClientHttpRequestFactory}</li>
* </ul> * </ul>
* A {@code requestFactoryType} of {@link ClientHttpRequestFactory} is equivalent to * A {@code requestFactoryType} of {@link ClientHttpRequestFactory} is equivalent to
@ -129,7 +130,7 @@ public final class ClientHttpRequestFactories {
* @param settings the settings to apply * @param settings the settings to apply
* @return a new {@link ClientHttpRequestFactory} instance * @return a new {@link ClientHttpRequestFactory} instance
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "removal" })
public static <T extends ClientHttpRequestFactory> T get(Class<T> requestFactoryType, public static <T extends ClientHttpRequestFactory> T get(Class<T> requestFactoryType,
ClientHttpRequestFactorySettings settings) { ClientHttpRequestFactorySettings settings) {
Assert.notNull(settings, "Settings must not be null"); Assert.notNull(settings, "Settings must not be null");
@ -139,9 +140,6 @@ public final class ClientHttpRequestFactories {
if (requestFactoryType == HttpComponentsClientHttpRequestFactory.class) { if (requestFactoryType == HttpComponentsClientHttpRequestFactory.class) {
return (T) HttpComponents.get(settings); return (T) HttpComponents.get(settings);
} }
if (requestFactoryType == OkHttp3ClientHttpRequestFactory.class) {
return (T) OkHttp.get(settings);
}
if (requestFactoryType == JettyClientHttpRequestFactory.class) { if (requestFactoryType == JettyClientHttpRequestFactory.class) {
return (T) Jetty.get(settings); return (T) Jetty.get(settings);
} }
@ -151,6 +149,9 @@ public final class ClientHttpRequestFactories {
if (requestFactoryType == SimpleClientHttpRequestFactory.class) { if (requestFactoryType == SimpleClientHttpRequestFactory.class) {
return (T) Simple.get(settings); return (T) Simple.get(settings);
} }
if (requestFactoryType == OkHttp3ClientHttpRequestFactory.class) {
return (T) OkHttp.get(settings);
}
return get(() -> createRequestFactory(requestFactoryType), settings); return get(() -> createRequestFactory(requestFactoryType), settings);
} }
@ -220,6 +221,8 @@ public final class ClientHttpRequestFactories {
/** /**
* Support for {@link OkHttp3ClientHttpRequestFactory}. * Support for {@link OkHttp3ClientHttpRequestFactory}.
*/ */
@Deprecated(since = "3.2.0", forRemoval = true)
@SuppressWarnings("removal")
static class OkHttp { static class OkHttp {
static OkHttp3ClientHttpRequestFactory get(ClientHttpRequestFactorySettings settings) { static OkHttp3ClientHttpRequestFactory get(ClientHttpRequestFactorySettings settings) {

@ -56,10 +56,6 @@ class ClientHttpRequestFactoriesRuntimeHints implements RuntimeHintsRegistrar {
typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.APACHE_HTTP_CLIENT_CLASS)); typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.APACHE_HTTP_CLIENT_CLASS));
registerReflectionHints(hints, HttpComponentsClientHttpRequestFactory.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) -> { hints.registerTypeIfPresent(classLoader, ClientHttpRequestFactories.JETTY_CLIENT_CLASS, (typeHint) -> {
typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.JETTY_CLIENT_CLASS)); typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.JETTY_CLIENT_CLASS));
registerReflectionHints(hints, JettyClientHttpRequestFactory.class, long.class); registerReflectionHints(hints, JettyClientHttpRequestFactory.class, long.class);
@ -68,6 +64,17 @@ class ClientHttpRequestFactoriesRuntimeHints implements RuntimeHintsRegistrar {
typeHint.onReachableType(HttpURLConnection.class); typeHint.onReachableType(HttpURLConnection.class);
registerReflectionHints(hints, SimpleClientHttpRequestFactory.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, private void registerReflectionHints(ReflectionHints hints,

@ -35,7 +35,9 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
@ClassPathOverrides("com.squareup.okhttp3:okhttp:3.14.9") @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 class ClientHttpRequestFactoriesOkHttp3Tests
extends AbstractClientHttpRequestFactoriesTests<OkHttp3ClientHttpRequestFactory> { extends AbstractClientHttpRequestFactoriesTests<OkHttp3ClientHttpRequestFactory> {

@ -33,7 +33,9 @@ import static org.assertj.core.api.Assertions.assertThat;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
@ClassPathExclusions("httpclient5-*.jar") @ClassPathExclusions({ "httpclient5-*.jar", "jetty-client-*.jar" })
@Deprecated(since = "3.2.0")
@SuppressWarnings("removal")
class ClientHttpRequestFactoriesOkHttp4Tests class ClientHttpRequestFactoriesOkHttp4Tests
extends AbstractClientHttpRequestFactoriesTests<OkHttp3ClientHttpRequestFactory> { extends AbstractClientHttpRequestFactoriesTests<OkHttp3ClientHttpRequestFactory> {

@ -63,6 +63,8 @@ class ClientHttpRequestFactoriesRuntimeHintsTests {
} }
@Test @Test
@Deprecated(since = "3.2.0")
@SuppressWarnings("removal")
void shouldRegisterOkHttpHints() { void shouldRegisterOkHttpHints() {
RuntimeHints hints = new RuntimeHints(); RuntimeHints hints = new RuntimeHints();
new ClientHttpRequestFactoriesRuntimeHints().registerHints(hints, getClass().getClassLoader()); new ClientHttpRequestFactoriesRuntimeHints().registerHints(hints, getClass().getClassLoader());

@ -70,6 +70,8 @@ class ClientHttpRequestFactoriesTests {
} }
@Test @Test
@Deprecated(since = "3.2.0")
@SuppressWarnings("removal")
void getOfOkHttpFactoryReturnsOkHttpFactory() { void getOfOkHttpFactoryReturnsOkHttpFactory() {
ClientHttpRequestFactory requestFactory = ClientHttpRequestFactories.get(OkHttp3ClientHttpRequestFactory.class, ClientHttpRequestFactory requestFactory = ClientHttpRequestFactories.get(OkHttp3ClientHttpRequestFactory.class,
ClientHttpRequestFactorySettings.DEFAULTS); ClientHttpRequestFactorySettings.DEFAULTS);

@ -18,12 +18,12 @@ package org.springframework.boot.webservices.client;
import java.time.Duration; import java.time.Duration;
import okhttp3.OkHttpClient; import org.eclipse.jetty.client.HttpClient;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.http.client.ClientHttpRequestFactory; 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.test.util.ReflectionTestUtils;
import org.springframework.ws.transport.WebServiceMessageSender; import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.ws.transport.http.ClientHttpRequestMessageSender; import org.springframework.ws.transport.http.ClientHttpRequestMessageSender;
@ -42,9 +42,9 @@ class HttpWebServiceMessageSenderBuilderOkHttp3IntegrationTests {
private final HttpWebServiceMessageSenderBuilder builder = new HttpWebServiceMessageSenderBuilder(); private final HttpWebServiceMessageSenderBuilder builder = new HttpWebServiceMessageSenderBuilder();
@Test @Test
void buildUseOkHttp3ByDefault() { void buildUseJettyClientIfHttpComponentsIsNotAvailable() {
WebServiceMessageSender messageSender = this.builder.build(); WebServiceMessageSender messageSender = this.builder.build();
assertOkHttp3RequestFactory(messageSender); assertJettyClientHttpRequestFactory(messageSender);
} }
@Test @Test
@ -52,19 +52,19 @@ class HttpWebServiceMessageSenderBuilderOkHttp3IntegrationTests {
WebServiceMessageSender messageSender = this.builder.setConnectTimeout(Duration.ofSeconds(5)) WebServiceMessageSender messageSender = this.builder.setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(2)) .setReadTimeout(Duration.ofSeconds(2))
.build(); .build();
OkHttp3ClientHttpRequestFactory factory = assertOkHttp3RequestFactory(messageSender); JettyClientHttpRequestFactory factory = assertJettyClientHttpRequestFactory(messageSender);
OkHttpClient client = (OkHttpClient) ReflectionTestUtils.getField(factory, "client"); HttpClient client = (HttpClient) ReflectionTestUtils.getField(factory, "httpClient");
assertThat(client).isNotNull(); assertThat(client).isNotNull();
assertThat(client.connectTimeoutMillis()).isEqualTo(5000); assertThat(client.getConnectTimeout()).isEqualTo(5000);
assertThat(client.readTimeoutMillis()).isEqualTo(2000); assertThat(factory).hasFieldOrPropertyWithValue("readTimeout", 2000L);
} }
private OkHttp3ClientHttpRequestFactory assertOkHttp3RequestFactory(WebServiceMessageSender messageSender) { private JettyClientHttpRequestFactory assertJettyClientHttpRequestFactory(WebServiceMessageSender messageSender) {
assertThat(messageSender).isInstanceOf(ClientHttpRequestMessageSender.class); assertThat(messageSender).isInstanceOf(ClientHttpRequestMessageSender.class);
ClientHttpRequestMessageSender sender = (ClientHttpRequestMessageSender) messageSender; ClientHttpRequestMessageSender sender = (ClientHttpRequestMessageSender) messageSender;
ClientHttpRequestFactory requestFactory = sender.getRequestFactory(); ClientHttpRequestFactory requestFactory = sender.getRequestFactory();
assertThat(requestFactory).isInstanceOf(OkHttp3ClientHttpRequestFactory.class); assertThat(requestFactory).isInstanceOf(JettyClientHttpRequestFactory.class);
return (OkHttp3ClientHttpRequestFactory) requestFactory; return (JettyClientHttpRequestFactory) requestFactory;
} }
} }

@ -13,9 +13,9 @@ dependencies {
testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test")) 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-tools:spring-boot-test-support"))
testImplementation(project(":spring-boot-project:spring-boot-testcontainers")) testImplementation(project(":spring-boot-project:spring-boot-testcontainers"))
testImplementation("com.squareup.okhttp3:okhttp")
testImplementation("io.projectreactor:reactor-core") testImplementation("io.projectreactor:reactor-core")
testImplementation("io.projectreactor:reactor-test") testImplementation("io.projectreactor:reactor-test")
testImplementation("org.apache.httpcomponents.client5:httpclient5")
testImplementation("org.junit.jupiter:junit-jupiter") testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("org.junit.platform:junit-platform-engine") testImplementation("org.junit.platform:junit-platform-engine")
testImplementation("org.junit.platform:junit-platform-launcher") testImplementation("org.junit.platform:junit-platform-launcher")

@ -17,13 +17,14 @@
package smoketest.data.couchbase; package smoketest.data.couchbase;
import java.time.Duration; import java.time.Duration;
import java.util.Base64;
import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse;
import okhttp3.Credentials; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import okhttp3.OkHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients;
import okhttp3.Request; import org.apache.hc.core5.http.ClassicHttpRequest;
import okhttp3.RequestBody; import org.apache.hc.core5.http.HttpResponse;
import okhttp3.Response; import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
import org.testcontainers.couchbase.CouchbaseContainer; import org.testcontainers.couchbase.CouchbaseContainer;
import org.testcontainers.utility.MountableFile; import org.testcontainers.utility.MountableFile;
@ -33,6 +34,7 @@ import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
* A {@link CouchbaseContainer} for Couchbase with SSL configuration. * A {@link CouchbaseContainer} for Couchbase with SSL configuration.
* *
* @author Scott Frederick * @author Scott Frederick
* @author Stephane Nicoll
*/ */
public class SecureCouchbaseContainer extends CouchbaseContainer { public class SecureCouchbaseContainer extends CouchbaseContainer {
@ -69,20 +71,26 @@ public class SecureCouchbaseContainer extends CouchbaseContainer {
} }
private void doHttpRequest(String path) { private void doHttpRequest(String path) {
Response response; HttpResponse response = post(path);
try { 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); String url = "http://%s:%d/%s".formatted(getHost(), getMappedPort(MANAGEMENT_PORT), path);
Request.Builder requestBuilder = new Request.Builder().url(url) ClassicHttpRequest httpPost = ClassicRequestBuilder.post(url)
.header("Authorization", Credentials.basic(ADMIN_USER, ADMIN_PASSWORD)) .addHeader("Authorization", basicAuth)
.post(RequestBody.create("".getBytes())); .setEntity("")
response = new OkHttpClient().newCall(requestBuilder.build()).execute(); .build();
return httpclient.execute(httpPost, (response) -> response);
} }
catch (Exception ex) { catch (Exception ex) {
throw new IllegalStateException("Error calling Couchbase HTTP endpoint", ex); throw new IllegalStateException("Error calling Couchbase HTTP endpoint", ex);
} }
if (!response.isSuccessful()) {
throw new IllegalStateException("Error calling Couchbase HTTP endpoint: " + response);
}
} }
} }

Loading…
Cancel
Save