I am trying to read an http stream using Apache's CloseableHttpClient. For regular URLs that return a single response, this has been working well, but I haven't had luck with streaming responses. My code runs in a thread. I would like to call the grabUrl() method to return an input stream, then do the reading/parsing in run().
Right now the code runs, but the socket closes after just a few bytes are read.
> java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at org.apache.hc.core5.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:149)
at org.apache.hc.core5.http.impl.io.SessionInputBufferImpl.read(SessionInputBufferImpl.java:203)
at org.apache.hc.core5.http.impl.io.IdentityInputStream.read(IdentityInputStream.java:99)
at org.apache.hc.core5.http.io.EofSensorInputStream.read(EofSensorInputStream.java:135)
at org.apache.hc.core5.http.io.EofSensorInputStream.read(EofSensorInputStream.java:148)
at org.example.R300NotificationsReader.run(R300NotificationsReader.java:114)
10:53:28 AM: Execution finished ':Main.main()'.
My suspicion is that either I'm doing something to close the socket, a local variable is getting deleted when I leave the function, or I just plain have the wrong http client for the job. I have the same function working using Python's Requests module, but I need to recreate it in Java, and this is my first time trying to work with HTTP endpoints in Java.
This is my grabUrl() function:
public InputStream grabUrl(String url, int messageID) {
ClassicHttpRequest httpGet = null;
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
if (url.equals(notificationNegotiateUrl)) {
httpGet = ClassicRequestBuilder.get(R300Utils.addParameters(url, messageID)).build();
}
else {
httpGet = ClassicRequestBuilder.get(R300Utils.addParametersWithToken(url, messageID, tid)).build();
}
CloseableHttpResponse response = httpClient.execute(httpGet);
System.out.println(response.getCode() + " " + response.getReasonPhrase());
if (response.getCode() >= 200 && response.getCode() < 300) {
// Get the response entity
HttpEntity entity = response.getEntity();
if (entity != null) {
// Return the input stream from the response entity
return entity.getContent();
}
}
}
catch (IOException e) {
System.out.println("There was an IO exception\n" + e.toString() );
}
return null;
}
And this is the thread's run() method:
@Override
public void run() {
try {
requestNegotiate();
System.out.println("Started Negotiate");
messageID += 1;
try (InputStream notificationStream = requestConnect()) {
messageID += 1;
System.out.println("Started connect");
if (notificationStream == null) {
System.out.println("connect returned null");
}
requestStart();
System.out.println("Started start notification stream");
if (notificationStream != null) {
byte[] data = new byte[100];
notificationStream.read(data);
System.out.println(data.toString());
}
while (notificationStream != null) {
byte[] inputBuffer = new byte[100];
notificationStream.read(inputBuffer);
System.out.println(inputBuffer.toString());
}
}
} catch (IOException e)
e.printStackTrace();
}
}
requestNegotiate(), requestConnect(), and requestStart() call one-line functions that just build the associated URL, then get passed along to grabUrl(). I have verified all the URLs are correct, so I didn't bother to include them in this post.
I've been stuck on this for a couple of days, so any guidance is greatly appreciated. Thanks!