-2

This is my cose:

private ResultSetType makeRequest() {
    try (CloseableHttpResponse response = this.sendRequest(request)) {
        String responseBody = IOUtils.toString(
            response.getEntity().getContent(),
            StandardCharsets.UTF_8
        );
            
        if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
            // do something;
            return ...
        } else {
            throw new LoaderSystemFault(LoaderConstants.ErrorCodes.ERR_002, "Communication error with Servei Territorial (status-code: {0} / request: {1} / response: {2})", response.getStatusLine().getStatusCode(), request, responseBody);
        }
    } catch (IOException | JAXBException e) {
        throw new LoaderSystemFault(LoaderConstants.ErrorCodes.ERR_002, "Communication error with Servei Territorial (status-code: {0} / request: {1} / response: {2})", response.getStatusLine().getStatusCode(), request, responseBody);
    }
}

My goal is to close CloseableHttpResponse.

Several questions here:

  • What about return statement inside try-catch-resources?
  • What about throw new statements?

It's not clear to me if CloseableHttpResponse will be closed regardless of whether return or thow new statements are reached.

How could I refactor above code?

Any ideas?

Jordi
  • 20,868
  • 39
  • 149
  • 333
  • 1
    It will be closed via all possible paths. No need to change your code. – user207421 Jun 10 '21 at 07:16
  • 1
    What are you trying to ask with "What about return statement inside try-catch-resources?" Isn't that already answered by "It's clear to me if CloseableHttpResponse will be closed regardless of whether return or thow new statements are reached."? – Sweeper Jun 10 '21 at 07:16
  • "What about X?" is not a clear question. What about those things is your question? – khelwood Jun 10 '21 at 07:17
  • @Sweeper miswritting, I meant "It's NOT clear to me". Solved. – Jordi Jun 10 '21 at 07:19
  • Well it doesn't help much when you ask the oppossite of what you mean. – user207421 Jun 10 '21 at 07:31

1 Answers1

1

According to the Java Language Specification, a try-with-resources like the one you have there is first translated to:

try {
    try (CloseableHttpResponse response = this.sendRequest(request)) {
        String responseBody = IOUtils.toString(
            response.getEntity().getContent(),
            StandardCharsets.UTF_8
        );
            
        if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
            // do something;
            return ...
        } else {
            throw new LoaderSystemFault(LoaderConstants.ErrorCodes.ERR_002, "Communication error with Servei Territorial (status-code: {0} / request: {1} / response: {2})", response.getStatusLine().getStatusCode(), request, responseBody);
        }
    }
} catch (IOException | JAXBException e) {
    throw new LoaderSystemFault(LoaderConstants.ErrorCodes.ERR_002, "Communication error with Servei Territorial (status-code: {0} / request: {1} / response: {2})", response.getStatusLine().getStatusCode(), request, responseBody);
}

The inner try-with-with resources is now a basic try-with-resources statement, and is translated like this:

{
    final CloseableHttpResponse response = this.sendRequest(request);
    Throwable #primaryExc = null;

    try {
        // everything in your try block
    } catch (Throwable #t) {
        #primaryExc = #t;
        throw #t;
    } finally {
        if (response != null) {
            if (#primaryExc != null) {
                try {
                    response.close();
                } catch (Throwable #suppressedExc) {
                    #primaryExc.addSuppressed(#suppressedExc);
                }
            } else {
                response.close();
            }
        }
    }
}

The important thing to note is that the block in the original try-with-resources gets translated to the try block of the try-catch-finally, and the closing of the resource is done in the finally block.

This means that the semantics of normal try-catch-finally statements apply here - if the try block completes abruptly (i.e. returns or throws) or if it completes normally, the finally block will get executed. See §14.20.2 for the exact details. You'll see that finally is executed in every case mentioned in the spec.

So in conclusion, your resource will be closed even if return or throw is reached.

Sweeper
  • 213,210
  • 22
  • 193
  • 313