1

I have a piece of code which reads the POST data from the Servlet Request's input stream. I am using java nio for reading the data.

For most cases and regular data, the code works perfectly fine. However in some cases where data is large (content length = 600000), the Channel's read method seems to fail with a Socket timeout error. Also this seems to happen only with IE 9, it is working fine with Firefox and Chrome.

While investigating this i figured, that while using IE, the post data seems to take a bit longer than the other browsers to be available for reading. So i put a Thread.sleep(400) before the code and the code started to work fine for IE as well.

I don't want to put a sleep before this code, one its just a workaround and not a proper solution, second, there is no correct sleep time, since if the data increases, 400 might not be enough.

Is there a way where i can tell the channel to not time out or remove the timeout altogether?

Below is code being used,

ReadableByteChannel channel = Channels.newChannel(inputStream);
byte[] postData = new byte[contentLength];
ByteBuffer buf = ByteBuffer.allocateDirect(contentLength);
int numRead = 0;
int counter = 0;
while (numRead >= 0) {
    buf.rewind();
    numRead = channel.read(buf);
    buf.rewind();
    for (int i = 0; i < numRead; i++) {
       postData[counter++] = buf.get();
    }
}
return postData;

The inputStream is directly via request.getInputStream() and content length is via request.getContentLength().

The container used is Tomcat 7.0.42 in embedded mode.

Victor
  • 1,207
  • 2
  • 13
  • 21
  • Post your code, then maybe we can help you! – isnot2bad Dec 11 '13 at 09:33
  • Is the POST request made from your client side code? If so, what technology is it? See the following post for http request timeouts in java: http://stackoverflow.com/questions/1414795/how-to-specify-http-request-timeout-parameter-on-java-servlet-container. – Mark Tielemans Dec 11 '13 at 09:36
  • @MarkTielemans, Yes the POST is made from the client side code. Using SmartGWT(a javascript toolkit). The link you mentioned seems to provide details around client side timeouts. While in my case the error seems to stem from server giving up, not waiting enough. – Victor Dec 11 '13 at 12:24
  • 1
    Are you using an out of the box tomcat config or have customizations been made? For example did someone set `connectionTimeout` or `connectionUploadTimeout` to some value thinking it was seconds, but they are really milliseconds. – Alcanzar Dec 11 '13 at 16:04
  • @Alcanzar, Not really, using standard configurations. All timeouts are set appropriately. – Victor Dec 17 '13 at 04:48

3 Answers3

0

Your read timeout is too short. Increase it.

But I would throw this NIO code away and just read directly from the input stream. With DataInputStream.readFully() it's one line of code. Your NIO code does that anyway but in a very roundabout way with several extra layers.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • How would one go about increasing the read timeout on a servlet obtained inputstream? I would expect it requires some amount of reworking the concrete client implementation? – Anders R. Bystrup Dec 11 '13 at 10:03
  • @Szymon This does provide an answer to the question, and it does not consist of, or even contain, a critique or a request for clarification. You are talking nonsense. – user207421 Dec 11 '13 at 10:08
  • @AndersR.Bystrup The read timeout for requests will be set in some configuration somewhere for your unnamed Servlet container, or else in your unstated code that maps an input stream into a channel. – user207421 Dec 11 '13 at 10:09
  • @Szymon Then the auto comment from the review comment is talking nonsense. All answers can be expanded. If you have a *specific* suggestion, kindly provide it. So far this is just noise. – user207421 Dec 11 '13 at 10:13
  • @EJP Added more details in the description. Only when i add Thread.sleep(400) above this code, it seems to work. This indicates server is not waiting enough for the POST data to be available. Any pointers as to where should a timeout be set if any. – Victor Dec 11 '13 at 12:25
  • Adding a sleep is just another way of increasing the timeout, and not a very good way. – user207421 Jan 05 '14 at 22:50
0

If you can read the content length header, you can increase the sleep time based on it. That should at least make your code function in different scenarios. It's a workaround of course, but it seems like a solid one. Alternatively, you can set the socket timeout wait to a higher number. This change will be for all your servlets however, and is much less flexible.

Mark Tielemans
  • 1,528
  • 3
  • 20
  • 40
0

Since i couldn't find any appropriate solution for this problem. I have continued with my existing work around i.e. sleep for some time. But the issue i had was how long do i sleep, since larger the data i would need to sleep more. And there is no correct way of knowing that, since i couldn't derive any formula out of the content length, the sleep times were random.

So the next best thing i could apply was, i caught the Socket Timeout Exception and sleep for the least minimum time that i knew was needed i.e. 400ms. And then tried again, set the logic for 3 retries before giving up. So far that has worked, for increasing amount of data.

Victor
  • 1,207
  • 2
  • 13
  • 21