2

I have the following java code with try with resources:

public static CloseableHttpResponse getHttpResponse()
    {
        try (CloseableHttpClient client = HttpClientBuilder.create().build()) {
            try (CloseableHttpResponse response = client.execute(request)) {
                return response;
            }
        }
    }

in another method will use the response returned by getHttpResponse:

public void test() {
        CloseableHttpResponse response = getHttpResponse();
        if (response) {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                // do something
            }
        }
    }

Looks like after CloseableHttpResponse response = getHttpResponse();, the client and response already closed, and I can not put this two methods into one, are there any ways that still use the try with resources in another method?

ratzip
  • 1,571
  • 7
  • 28
  • 53

2 Answers2

1

The best approach is the Execute Around idiom. Instead of getHttpResponse returning a CloseableHttpResponse pass in a lambda (typically) to be executed. The resource can then be closed in a try-with-resource statement cleanly.

/*** NICE ***/
// Function instead of Consumer would allow the method to return a value.
private void httpResponse(
    Consumer<CloseableHttpResponse> op
) /* throws IOException */ {
    try (CloseableHttpClient client = HttpClientBuilder.create().build()) {
        try (CloseableHttpResponse response = client.execute(request)) {
            if (response != null) { // Really?
                op.accept(response);
            }
        }
    }
}

Used as:

    httpResponse(response -> {
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == HttpStatus.SC_OK) {
            // do something
        }
    });

The hacky alternative is to include a try statement within getHttpResponse that only closed in error conditions.

/*** HACKY ***/
private CloseableHttpResponse httpResponse() /* throws IOException */ {
    boolean success = false;
    CloseableHttpClient client = HttpClientBuilder.create().build();
    try {
        CloseableHttpResponse response = client.execute(request);
        try {
            success = true;
            return response;
        } finally {
            if (!success) {
                response.close();
            }
        }
    } finally {
        if (!success) {
            client.close();
        }
    }
}
Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
0

client will be closed as soon as the program leaves the scope of the try-with-resources. Can you try building the try with resources around the getHttpResponse method? For example:

public static CloseableHttpResponse getHttpResponse() {
    try (CloseableHttpClient client = HttpClientBuilder.create().build()) {
        CloseableHttpResponse response = client.execute(request)
        return response;
    }
}

And then you can rewrite your test method() like this:

public void test() {
    try(CloseableHttpResponse response = getHttpResponse()) {
        if (response) {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                // do something
            }
        }
    }
}
Jaeheon Shim
  • 491
  • 5
  • 14
  • In this way, when client is closed as the program out of the try-with-resources, can the response is still valid? – ratzip Feb 28 '20 at 16:25
  • I'm not quite sure, but my guess is that the response would no longer be valid because response is a stream over the content from the network socket – Jaeheon Shim Feb 28 '20 at 16:33