Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2036182 | 1.4.0 | Michael McMahon | P4 | Resolved | Fixed | beta |
Name: stC104175 Date: 08/10/2000
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)
We use the java.net.URL class to manage a server request to a servlet.
There is a transfer of binary data between the client and the servlet,
where Objects are serialized via ByteArrayStreams and transfered as
a byte[] like this:
public byte[] requestBytes(byte[] rData)
{
byte[] lResult = null;
URL lURL = new URL("http://servername/servlets/TestServlet");
HttpURLConnection lCon = (HttpURLConnection) lURL.openConnection();
lCon.setDoOutput(true);
lCon.setDoInput(true);
lCon.setUseCaches(false);
lCon.setRequestMethod("POST");
lCon.setRequestProperty("Content-Type", "application/octet-stream");
OutputStream lOut = lCon.getOutputStream();
lOut.write(rData);
lOut.close(); // Does not change behaviour, if not present
// until here anything works fine, servlet gets all data and responds
// correct (could be checked with Internet Explorer download)
System.out.println(lCon.getContentEncoding()); // is null whatever the
// servlet responds
InputStream lIn = lCon.getInputStream(); // with -Dhttp.keepAlive=false
// this could takes about 5 Minutes
int liSize = lCon.getContentLength(); // is -1, if data exceeds a certain
// amount or data is transfered via
// a proxy server
System.out.println("RespCode: "+lCon.getResponseCode()); // is 200
System.out.println("RespMsg: "+lCon.getResponseMessage()); // is 'OK'
if (liSize > 0)
lResult = StreamScan.blockread(lIn,liSize);
else
lResult = StreamScan.blockreadFully(lIn);
// lIn.close(); // does not change behavior, if present
return lResult;
}
StreamScan.blockread reads streamdata with respect to timeout values like this:
public class StreamScan
{
private static final int giK_BlockSize = 8192;
private static final long glK_TimeoutMillis = 800;
private static final long glK_BlockTimeoutMillis = 5000;
private static final long glK_SleepMillis = 200;
private static final long glK_BlockSleepMillis = 500;
private static int blockread(InputStream rInput,
byte[] rbyBuffer, int viBufPos, int viLen)
{
int liBytesAvailable;
int liByte;
int liTotalBytesRead = 0;
int liBufPos = viBufPos;
if (rbyBuffer == null)
return -1;
int liLen = Math.min(viLen,rbyBuffer.length-viBufPos);
try {
do
{ // wait for data to become available or timeout is reached
if ((liBytesAvailable = rInput.available()) == 0)
{
long llTimerStart = System.currentTimeMillis();
do
{
try {Thread.currentThread().sleep(glK_BlockSleepMillis);}
catch (InterruptedException ex) {}
} while (((liBytesAvailable = rInput.available()) == 0) &&
((System.currentTimeMillis() - llTimerStart) < glK_BlockTimeoutMillis));
}
// cancel, if timed out
if (liBytesAvailable == 0)
return liTotalBytesRead;
// read available bytes
while ((liTotalBytesRead < liLen) && (liBytesAvailable > 0))
{
liByte = rInput.read();
if (liByte == -1) return -1; // should not really happen
rbyBuffer[liBufPos++] = (byte) liByte;
liTotalBytesRead++;
liBytesAvailable--;
}
} while (liTotalBytesRead < liLen);
return liTotalBytesRead;
}
catch (Exception e) {return -1;}
}
public static byte[] blockread(InputStream rInput, int viLen)
{
byte[] lbyBuffer = new byte[viLen];
if ((StreamScan.blockread(rInput,lbyBuffer,0,viLen)) < viLen)
return null;
else
return lbyBuffer;
}
}
The problem is, that this doesn't work stable. Often there is a content length
of -1 reported from the HttpURLConnection and indeed there could be read no data
from the stream. But the data IS sent from the servlet as we could prove with
a download from a browser. Anythings well until we try to get the InputStream
and read from it.
We thought it to be related to the keepAlive problem and tried the
-Dhttp.keepAlive=false parameter to java.exe, but things get even more curious
with that. Now sometimes we didnt even get the InputStream from the
HttpURLConnection (or it took until 10 Minutes!!! to get the stream and the
content was cut after a few bytes). Switching off the keepAlive in the Internet
Information Server didnt change anything by the way.
Our environtment is an NT 4 Server (SR6) with IIS4 and the JRun Servlet Engine.
Client and server are working with the JRE 1.3
After weeks of testing we believe this to be a bug of the HttpURLConnection.
It seems, as if the connection interprets a keepAlive message as the data packet
with empty content or something alike. Very strange.
Bye the way, here's the servlet code:
...
byte[] lBuf = Meta.serialize(lTrans); // binary representation of an Object
System.out.println("lBufSize: "+lBuf.length);
response.setContentType("application/octet-stream");
response.setContentLength(lBuf.length); // doesnt change anything, if missing
// response.setHeader("Transfer-Encoding","chunked-data"); // doesnt any matter
// response.setHeader("Content-Encoding","binary"); // doesnt matter either
OutputStream lOut = response.getOutputStream();
lOut.write(lBuf);
...
very simple, isnt it?
(Review ID: 108179)
======================================================================
- backported by
-
JDK-2036182 HTTPUrlConnection does not receive binary data correctly
- Resolved
- relates to
-
JDK-4242616 HTTP URLConnection does not retry POST correctly (re-open 4099926)
- Closed