swagger-api / swagger-api/swagger-codegen-generators

"Connection is still allocated" when deserializing InputStream return type

Open
#1,198 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Mustache
Stars
299
Forks
439
PR merge metrics
No merged PRs in 30d

Description

Hello,

I just found a strange behaviour in ApiClient.invokeAPI, when deserializing a second response of InputStream after a first one with the same type. The error stack shows :
RESTEASY004655: Unable to invoke request .... Caused by: java.lang.IllegalStateException: Connection is still allocated
After debugging, I saw that the first response was not consumed globally wich causes the stack reason. So,I closed the response here :

else if (response.getStatusInfo().getFamily().equals(Status.Family.SUCCESSFUL)) {
      if (returnType == null) {
        return null;
      } else {
        T parsedResponse = deserialize(response, returnType);
        response.close();
        return parsedResponse;
      }
    } 

The problem seems to be resolved and I can call the second response successfully BUT a new problem showed when deserializing the response entity ( wich is the inputstream ). The method deserialize does not handle the inputstream case so it is treated like that : : T parsedResponse = response.readEntity(returnType). This assertion close the inputstream, so it cant be readed anymore and blocks the operation. So I updated the method this way :

public <T> T deserialize(Response response, GenericType<T> returnType) throws ApiException {
    if (response == null || returnType == null) {
      return null;
    }

    if ("byte[]".equals(returnType.toString())) {
      // Handle binary response (byte array).
      return (T) response.readEntity(byte[].class);
    } else if (returnType.equals(File.class)) {
      // Handle file downloading.
      @SuppressWarnings("unchecked")
      T file = (T) downloadFileFromResponse(response);
      return file;
    }
    else if (returnType.getType().equals(InputStream.class)) {
      return downloadInputStreamFromResponse(response);
    }

    String contentType = null;
    List<Object> contentTypes = response.getHeaders().get("Content-Type");
    if (contentTypes != null && !contentTypes.isEmpty()) {
      contentType = String.valueOf(contentTypes.get(0));
    }
    if (contentType == null) {
      throw new ApiException(500, "missing Content-Type in response");
    }

    T parsedResponse = response.readEntity(returnType);
    return parsedResponse;
  }
private <T> T downloadInputStreamFromResponse(Response response) {
 File file = downloadFileFromResponse(response);
 try {
   return (T) new FileInputStream(file);
 } catch (FileNotFoundException e) {
   throw new RuntimeException(e);
 } finally {
   FileUtils.deleteQuietly(file);
 }
}

Then everything went so good.
I suggest adding those updates, and if anyone have the same problem, he can add it to his ApiClient.mustache or generate his own ApiClient.java.

Best regards,

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in ApiClient.mustache and inspect ApiClient.invokeAPI and deserialize for successful responses and InputStream return types. Compare the reported response-closing and InputStream handling behavior, then verify that repeated InputStream responses remain usable without leaving the connection allocated.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.