SpringBoot upgrade RestTemplateBuilder from 1.5.14 to 2.1.5
You don't need a builder here anymore as the supplier builds the ClientHttpRequestFactory on demand. Define the RequestFactorySupplier and the RestTemplateBuilder as beans.
@Bean
Supplier<ClientHttpRequestFactory> myRequestFactorySupplier() {
return () -> {
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
HttpClient httpClient = clientBuilder.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
requestFactory.setConnectTimeout(5000);
requestFactory.setReadTimeout(5000);
requestFactory.setBufferRequestBody(false);
return requestFactory;
};
}
@Bean
public RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder();
}
Use the factory in the controller like this.
@RestController
public class TestController {
private final RestTemplate restTemplate;
public TestController(
RestTemplateBuilder restTemplateBuilder,
Supplier<ClientHttpRequestFactory> myRequestFactorySupplier
) {
this.restTemplate = restTemplateBuilder
.requestFactory(myRequestFactorySupplier)
.build();
}
Of course you could also use a specialized class.
public class MyRequestFactorySupplier implements Supplier<ClientHttpRequestFactory> {
@Override
public ClientHttpRequestFactory get() {
// Using Apache HTTP client.
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
HttpClient httpClient = clientBuilder.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
requestFactory.setBufferRequestBody(false); // When sending large amounts of data via POST or PUT, it is recommended to change this property to false, so as not to run out of memory.
return requestFactory;
}
}
using it in the controller as you proposed:
public TestController(
RestTemplateBuilder restTemplateBuilder,
Supplier<ClientHttpRequestFactory> myRequestFactorySupplier
) {
this.restTemplate = restTemplateBuilder
.setConnectTimeout(Duration.ofMillis(5000))
.setReadTimeout(Duration.ofMillis(5000))
.requestFactory(new MyRequestFactorySupplier())
.build();
}
I have wrote detail notes on my github wiki page , please check sure will be helpful
- https://github.com/vaquarkhan/vaquarkhan/wiki/RestTemplate-vs-WebClient
Here is example :
public String retrieveData(String id, String name) {
HttpHeaders headers =createHeader();
String requestJson = "{\"name\":\"" + name + "\"}";
HttpEntity<String> request = new HttpEntity<String>(requestJson, headers);
// external call time
long startTime = System.currentTimeMillis();
ResponseEntity<String> response = customRestTemplate().exchange(externalUrl, HttpMethod.POST, request,
String.class);
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime); // divide by 1000000 to get milliseconds.
log.info("{\"RestTemplateDemo\":{\"id\":\"" + id + "\",\"external call duration\":" + duration + "}}");
ObjectMapper mapper = new ObjectMapper();
return response.getBody();
}
The below code shows how you need to create the template for simple cases.
RestTemplate tmpl = new RestTemplateBuilder().setConnectTimeout(Duration.ofMillis(200))
.setReadTimeout(Duration.ofMillis(100))
.requestFactory(org.springframework.http.client.SimpleClientHttpRequestFactory.class)
.build();
It would be better for you to provide the source code of MyHttpComponentFactoryBuilder
class. But my suggestion is that to create a class MyHttpComponentFactory
which extends SimpleClientHttpRequestFactory
class migrate your codes from MyHttpComponentFactoryBuilder
to it.