0

I'm struggling with an issue that seems to be much more complicated than I initially though.

I use an SDK which passes me an InputStream which I should use to make an http request(the stream is used to set the body - it is optional for some requests). I'm using the HttpURLConnection to make the request and get the response.

The problem appears as soon as I send the InputStream (it is found inside an custom model object) to another class through an static method.

RequestManager.startRequest(request, callback);

the request contains the InputStream. At this point it seems to be valid.

As soon as the InputStream is tried to be accessed in the RequestManager class or in other classes it is empty.

I must point out that it is sent to another thread which is handled by the RequestManager.

What could be the problem? I made some debugs and the InputStream seems to be the same object that it was sent by the SDK. Could something happen to the InputStream while the thread runs?

LE(method for read InputStream):

private String readStream(InputStream inputStream) {
        BufferedReader br = new BufferedReader(new InputStreamReader((inputStream)));
        StringBuilder sb = new StringBuilder();
        String output;
        try {
            while ((output = br.readLine()) != null) {
                sb.append(output);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }

If I use this method right before calling startRequest() it returns the String which should be set as the body of the request.

As soon as I try to use this method inside the manager, it returns an empty String.

LE: Added Screenshots of debug InputStream received from the SDK InputStream received from the SDK Read InputStream from SDK - before sending it to manager Read InputStream from SDK - before sending it to manager Read InputStream inside the manager before setting the body Read InputStream inside the manager before setting the body

LE: update

I have made more tests and it seems this is happening when the InputSream is accessed from another thread directly. If the InputStream is accessed on the same Thread that was created, everything is working fine, but as soon as some other Thread tries to access it becomes unavailable (it seems the read is blocked).

Ionut Negru
  • 6,186
  • 4
  • 48
  • 78
  • `I use an SDK`. Pretty vague. – greenapps Aug 15 '15 at 09:27
  • From where it comes, it is not relevant. If it makes more sense I will remove SDK from the question :) – Ionut Negru Aug 15 '15 at 09:28
  • Do you mean that stream is responsed from the server, for example, response.getInputStream(), then you want to process it? – BNK Aug 15 '15 at 09:39
  • No, InputStream is received to create the body of the HTTP request. When I receive the stream, it seems fine, as soon as I pass the object which contains the stream to my manager (which will handle multiple tasks and handle the background threads) the stream is unreadable (empty). – Ionut Negru Aug 15 '15 at 09:41
  • But does that stream received from an HTTP response? If so, when creating your object, you should copy that original stream to another stream (this new stream will be used for building the object) for future process. – BNK Aug 15 '15 at 09:44
  • No, the stream I'm having trouble with is not from the HTTP response. It is an custom InputStream which should contain some information that will be set in the body of the HTTP request I will make. – Ionut Negru Aug 15 '15 at 09:46
  • I think you should post your code for more information. – BNK Aug 15 '15 at 09:48
  • Defne 'unreadable (empty)'. If you've already read an `InputStream` to end of stream, you can't read it again.Ditto if you've closed it. Too vague. – user207421 Aug 15 '15 at 09:49
  • I knew this, but the thing is, this is happening even if I don't read the stream until the last moment when I need it (not even for debug purposes). And it still gets empty at some point ... Do you think it would be much safer to use an simple String instead, which I will simply set it to the OutputStream of the request? – Ionut Negru Aug 15 '15 at 09:53
  • 'This is happening.' **What** is happening? – user207421 Aug 15 '15 at 09:54
  • Empty stream. This was what we were talking about, right? – Ionut Negru Aug 15 '15 at 09:55
  • I think it is because of you read the stream twice, perhaps. If so, call inputStream.reset() before the second read. – BNK Aug 15 '15 at 09:57
  • At some point I was doing this mistake, but even when I removed every read and left only, the problem still appeared. This is what is bugging me... – Ionut Negru Aug 15 '15 at 09:58
  • I don't know what you were talking about. That's why I asked you to define it. You haven't yet done so. 'Unreadable' and 'empty' are mutually contradictory, – user207421 Aug 15 '15 at 09:59
  • Since i am not with my PC now and have not more your code, I can help you effectly. Sorry for that. Try searching more. – BNK Aug 15 '15 at 10:01
  • 'If I use this method right before calling startRequest() it returns the String which should be set as the body of the request. As soon as I try to use this method inside the manager, it returns an empty String.' The explication is in the question. I also explained again in the comments what was the issue. Please read the question again, or we can chat directly if you want more details. – Ionut Negru Aug 15 '15 at 10:01
  • 1
    Thank you Chung Pham, I will try and find the issue. – Ionut Negru Aug 15 '15 at 10:02
  • @IonutNegru If you're not prepared to define what you mean by 'unreadable', 'empty', and all the other vague terminology you have used here, it is impossible for anyone to hep you. If you're getting an exception, post it. It looks to me like you're closing the stream before it's read by the other thread, and ignoring the exception that results, but only you can say. You should get it working properly without the extra thread first, and then elaborate. – user207421 Aug 15 '15 at 10:07
  • @EJP, There are no exceptions thrown at read, the read simply returns an empty String after the Object which contains the InputStream is sent to my manager. Nothing is done to the object and it is used as it is. I have explained in the question what I meant (please read it again), I have also explained in the comments what I meant. I cannot explain something else. The read returns an empty String, no exception, no nothing... – Ionut Negru Aug 15 '15 at 10:10
  • Can you show the screenshot of debugging (at the phase read in manager), sorry for my bad English :-) – BNK Aug 15 '15 at 10:16
  • I have added some SS showing the InputStream. – Ionut Negru Aug 15 '15 at 10:33
  • Offset is different. Reset stream before the 2nd read :-) – BNK Aug 15 '15 at 10:34
  • The reads were not done on the same run, to avoid reading the InputStream twice... – Ionut Negru Aug 15 '15 at 10:36
  • Try reset and check the final result. – BNK Aug 15 '15 at 10:41

1 Answers1

0

As we discuss above, the offsets are different. So you should reset the stream (inputStream.reset();)before the 2nd read. This is my suggestion and answer. Hope this help!

UPDATE:

According to InputStream description

public synchronized void reset ()

Resets this stream to the last marked location. Throws an IOException if the number of bytes read since the mark has been set is greater than the limit provided to mark, or if no mark has been set.

I think you should check all your codes again

Moreover, refer to the following questions, hope you fix your issue soon:

  1. InputStream will not reset to beginning
  2. Read stream twice
Community
  • 1
  • 1
BNK
  • 23,994
  • 8
  • 77
  • 87
  • Calling reset() throws an IOException. If I do the read without the reset() method, the method still returns an empty String. I really do not understand where the InputStream gets messed up, but it is clear something is happening to it until it reaches my read method. I only have one usage of the getHttpRequest().getBody() which is used to set the parameter for the readStream() method. – Ionut Negru Aug 15 '15 at 11:10
  • So, post screenshot of that exception, or you should post more code relating to this issue. – BNK Aug 15 '15 at 12:01
  • The exception is of type IOException with an empty message, but it is at the line with the reset(). Sorry, but I can't post the whole code. I tried to put the relevant parts (as that is the only place where I touch the InputStream). Anyway, I think I will make an request to change it from InputStream to String as it will fix all these issue, but still, the issues is very strange ... – Ionut Negru Aug 15 '15 at 12:04
  • 1
    I think you can try another simpler project with the same logic to check more. – BNK Aug 15 '15 at 12:22
  • 1
    An good idea, but now I don't have time, I put this issue on hold. As soon as I have time I will test it more. Thank you for the suggestion. – Ionut Negru Aug 15 '15 at 12:24