In existing project I have an HTTP service that fetches data using Apache's HttpClient 4 and returns response InputStream
like in this code example:
public class HttpClient4Demo {
public static void main(String[] args) throws IOException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
try (Scanner scanner = new Scanner(fetchData(httpClient))) {
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
}
}
private static InputStream fetchData(HttpClient httpClient) throws IOException {
HttpResponse response = httpClient.execute(new HttpGet(
"https://dummyjson.com/products/1"
));
return response.getEntity().getContent();
}
}
I want to migrate that service to Apache's HttpClient 5, so I have to rewrite the code:
public class HttpClient5Demo {
public static void main(String[] args) throws IOException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
try (Scanner scanner = new Scanner(fetchData(httpClient))) {
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
}
}
private static InputStream fetchData(HttpClient httpClient) throws IOException {
ClassicHttpResponse response = httpClient.executeOpen(
null,
new HttpGet("https://dummyjson.com/products/1"),
null
);
return response.getEntity().getContent();
}
}
But that code gives me a warning because ClassicHttpResponse
is used without try-with-resources.
If I wrap ClassicHttpResponse
with try-with-resources, I'll get a closed InputStream
, so I won't be able to read response data.
private static InputStream fetchData(HttpClient httpClient) throws IOException {
try (ClassicHttpResponse response = httpClient.executeOpen(
null,
new HttpGet("https://dummyjson.com/products/1"),
null
)) {
return response.getEntity().getContent();
}
}
I can additionally wrap response.getEntity()
into ByteArrayInputStream
, and I will get a valid InputStream
, but it's not a perfect solution, since the whole response data will be stored in RAM.
private static InputStream fetchData(HttpClient httpClient) throws IOException {
try (ClassicHttpResponse response = httpClient.executeOpen(
null,
new HttpGet("https://dummyjson.com/products/1"),
null
)) {
return new ByteArrayInputStream(EntityUtils.toByteArray(response.getEntity()));
}
}
So is there any way to get response InputStream
without closing it and/or storing it in RAM using HttpClient 5?
Simple way
To get rid of the warning, return
ClassicHttpResponse
instead of theInputStream
, and put it in the try-with-resources clause as below.Since closing the
ClassicHttpResponse
is equivalent to closing theInputStream
, if you can ensure theInputStream
is properly closed after returning, the warning could be ignored also.You may feel a bit uncomfortable, that's why it comes to the recommended way.
Recommended way
Checking HttpClient#executeOpen, which is actually calling a deprecated method HttpClient#execute.
We can refer to example demonstrates the recommended way of processing the HTTP response, and the processing will be something like below
return null
looks a bit weird here, but in actual scenario, we usually map the response to another object and return it.Reference: Migration to Apache HttpClient 5.x classic APIs