Revisit resource cleanup in ClientHttpRequestFactory

Prior to this commit, resource management around
`ClientHttpRequestFactory` and `RestTemplate` was unclear. Some
factories implementation were implementing a `DisposableBean` and other
contracts were not managing request factory resources.

In the meantime, neither `ClientHttpRequestFactory` nor `RestTemplate`
are typically meant to be contributed as beans to the application
context. Most often, they're instantiated within beans and their
lifecycle should be managed by those.

This commit makes all `ClientHttpRequestFactory` `Closeable` and ensures
that all existing implementations have a similar behavior between
`dispose()` and `close()`. Since `RestTemplate` (actually
`HttpAccessor`) can instantiate factories on its own, they also now
extend `Closeable` to properly close those resources, if not externally
managed.

Closes gh-29010
This commit is contained in:
Brian Clozel
2022-09-13 15:53:01 +02:00
parent 71f9a84d22
commit 19d991a67b
6 changed files with 56 additions and 32 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,6 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
@@ -47,17 +46,15 @@ abstract class AbstractHttpRequestFactoryTests extends AbstractMockWebServerTest
@BeforeEach
final void createFactory() throws Exception {
factory = createRequestFactory();
if (factory instanceof InitializingBean) {
((InitializingBean) factory).afterPropertiesSet();
this.factory = createRequestFactory();
if (this.factory instanceof InitializingBean) {
((InitializingBean) this.factory).afterPropertiesSet();
}
}
@AfterEach
final void destroyFactory() throws Exception {
if (factory instanceof DisposableBean) {
((DisposableBean) factory).destroy();
}
this.factory.close();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,22 +55,24 @@ public class HttpComponentsClientHttpRequestFactoryTests extends AbstractHttpReq
@Test
public void assertCustomConfig() throws Exception {
HttpClient httpClient = HttpClientBuilder.create().build();
HttpComponentsClientHttpRequestFactory hrf = new HttpComponentsClientHttpRequestFactory(httpClient);
hrf.setConnectTimeout(1234);
hrf.setConnectionRequestTimeout(4321);
hrf.setReadTimeout(4567);
HttpComponentsClientHttpRequest request;
try (HttpComponentsClientHttpRequestFactory hrf = new HttpComponentsClientHttpRequestFactory(httpClient)) {
hrf.setConnectTimeout(1234);
hrf.setConnectionRequestTimeout(4321);
hrf.setReadTimeout(4567);
URI uri = new URI(baseUrl + "/status/ok");
HttpComponentsClientHttpRequest request = (HttpComponentsClientHttpRequest)
hrf.createRequest(uri, HttpMethod.GET);
URI uri = new URI(baseUrl + "/status/ok");
request = (HttpComponentsClientHttpRequest)
hrf.createRequest(uri, HttpMethod.GET);
Object config = request.getHttpContext().getAttribute(HttpClientContext.REQUEST_CONFIG);
assertThat(config).as("Request config should be set").isNotNull();
assertThat(config).as("Wrong request config type " + config.getClass().getName()).isInstanceOf(RequestConfig.class);
RequestConfig requestConfig = (RequestConfig) config;
assertThat(requestConfig.getConnectTimeout()).as("Wrong custom connection timeout").isEqualTo(1234);
assertThat(requestConfig.getConnectionRequestTimeout()).as("Wrong custom connection request timeout").isEqualTo(4321);
assertThat(requestConfig.getSocketTimeout()).as("Wrong custom socket timeout").isEqualTo(4567);
Object config = request.getHttpContext().getAttribute(HttpClientContext.REQUEST_CONFIG);
assertThat(config).as("Request config should be set").isNotNull();
assertThat(config).as("Wrong request config type " + config.getClass().getName()).isInstanceOf(RequestConfig.class);
RequestConfig requestConfig = (RequestConfig) config;
assertThat(requestConfig.getConnectTimeout()).as("Wrong custom connection timeout").isEqualTo(1234);
assertThat(requestConfig.getConnectionRequestTimeout()).as("Wrong custom connection request timeout").isEqualTo(4321);
assertThat(requestConfig.getSocketTimeout()).as("Wrong custom socket timeout").isEqualTo(4567);
}
}
@Test