Simon Roberts simon at dancingcloudservices.com
Tue May 15 15:10:40 UTC 2018


If I understand you correctly, you are saying that the "simple" version of
the code-code by the way that the project's main web page presents as it's
first example--is so simple that it's actually unusable in any production
scenario. I know I cannot use code for production that fails to read any
data from a (presumably) merely mis-configured server (a server from which
all other tools successfully read data. Did I interpret correctly, or did I
miss something? If correctly, I'd be surprised if that doesn't strike you
as sub-optimal to the point your pride in your work would want to make it
more usable.

It doesn't seem inappropriate to report a "warning" situation using an
exception? Would not an aggregate return that includes data, headers,
status code, ... and warnings be more helpful in this case? Mis-configured
servers (assuming that's the cause) are not uncommon around the web.

But perhaps more importantly, whatever the problem is, it is not fixed by
your code. The error is actually thrown by the *send* call, as I've now
determined as a result of trying your code. (I modified it very slightly so
as to complete it, and catch the exception.)

  public static void main(String[] args) /*throws Throwable */ {
    HttpClient client = HttpClient.newHttpClient();
    URI uri = URI.create("http://192.168.1.102:8080/index.html");

    HttpRequest getRequest = HttpRequest.newBuilder()
        .uri(uri)
        .GET()
        .build();

    try {
      HttpResponse<InputStream> response = client.send(getRequest,
          HttpResponse.BodyHandler.asInputStream());
      System.out.println("response: " + response);

      response.headers().firstValue("content-length")
          .ifPresent(cl -> System.out.println("content-length:" + cl));

      InputStream is = response.body();
      byte[] bytes = new byte[64 * 1024];
      int read = 0, count;
      try {
        while ((count = is.read(bytes, read, bytes.length - read)) != -1)
          read += count;
      } catch (IOException e) {
        System.err.println("Ignoring " + e);
      }
      System.out.println("bytes read: " + read);
      String bodyAsString = new String(bytes, StandardCharsets.UTF_8);
      System.out.println("body: " + bodyAsString);
    } catch (Throwable t) {
      System.out.println("Bang: ");
      t.printStackTrace();
    }
  }

the output follows (note, this is the *entire* output from the program. So
far as I can see, there is no mention of my code in the exception stack
trace (which seems to be a mistake in itself, as it's rather hard to track
down where an error occurred if it's not even mentioned in the trace). I
for my part will turn my attention to getting going with a different server:

/usr/local/jdk-10.0.1/bin/java
-javaagent:/home/simon/idea/idea-IC-181.4445.78/lib/idea_rt.jar=40188:/home/simon/idea/idea-IC-181.4445.78/bin
-Dfile.encoding=UTF-8 -p /home/simon/IdeaProjects/tentest/target/classes -m
tentest/httpstuff.Smartass
WARNING: Using incubator modules: jdk.incubator.httpclient
Bang:
java.io.EOFException: EOF reached while reading
at
jdk.incubator.httpclient/jdk.incubator.http.Http1AsyncReceiver$Http1TubeSubscriber.onComplete(Http1AsyncReceiver.java:507)
at
jdk.incubator.httpclient/jdk.incubator.http.SocketTube$InternalReadPublisher$ReadSubscription.signalCompletion(SocketTube.java:551)
at
jdk.incubator.httpclient/jdk.incubator.http.SocketTube$InternalReadPublisher$InternalReadSubscription.read(SocketTube.java:728)
at
jdk.incubator.httpclient/jdk.incubator.http.SocketTube$SocketFlowTask.run(SocketTube.java:171)
at
jdk.incubator.httpclient/jdk.incubator.http.internal.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
at
jdk.incubator.httpclient/jdk.incubator.http.internal.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
at
jdk.incubator.httpclient/jdk.incubator.http.internal.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
at
jdk.incubator.httpclient/jdk.incubator.http.SocketTube$InternalReadPublisher$InternalReadSubscription.signalReadable(SocketTube.java:675)
at
jdk.incubator.httpclient/jdk.incubator.http.SocketTube$InternalReadPublisher$ReadEvent.signalEvent(SocketTube.java:829)
at
jdk.incubator.httpclient/jdk.incubator.http.SocketTube$SocketFlowEvent.handle(SocketTube.java:243)
at
jdk.incubator.httpclient/jdk.incubator.http.HttpClientImpl$SelectorManager.handleEvent(HttpClientImpl.java:769)
at
jdk.incubator.httpclient/jdk.incubator.http.HttpClientImpl$SelectorManager.run(HttpClientImpl.java:731)

Process finished with exit code 0


On Tue, May 15, 2018 at 8:38 AM Chris Hegarty <chris.hegarty at oracle.com>
wrote:

> Simon,
>
> > On 15 May 2018, at 14:47, Simon Roberts <simon at dancingcloudservices.com>
> wrote:
> >
> > Chris, I'm OK with the idea that the program might be "operating in a
> broken environment”
>
> You may be ok with that, but many folk will not.
>
> > but I find it had to accept the idea that "it's not a crash" as useful.
>
> A recoverable exception in Java are not deemed as a “crash”.
>
> > By the time the exception is thrown, I cannot access the data. Merely
> telling the caller that there was an inconsistency in the server (which I
> think we're assuming is true) has rendered the data unreachable.
>
> That depends on your particular usage of the API, for example you could
> do something like:
>
>   HttpResponse<InputStream> response = client.send(getRequest,
>           HttpResponse.BodyHandler.asInputStream());
>   System.out.println("response: " + response);
>   response.headers().firstValue("content-length")
>           .ifPresent(cl -> System.out.println("content-length:" + cl));
>   InputStream is = response.body();
>   byte[] bytes = new byte[64*1024];
>   int read = 0, count;
>   try {
>       while ((count = is.read(bytes, read, bytes.length - read)) != -1)
>           read += count;
>   } catch (IOException e) {
>       System.err.println("Ignoring " + e);
>   }
>   System.out.println("bytes read: " + read);
>   String bodyAsString = new String(bytes, StandardCharsets.UTF_8);
>   System.out.println("body: " + bodyAsString);
>
>
> > Since every other test mechanism at my disposal survives whatever
> inaccuracy the node server is producing, it seems a bit ... well, let's say
> "unforgiving" that this code treats it as an unrecoverable failure.
>
> The API allows for the whole response, including the body, to be retrieved
> completely asynchronously, i.e. through one of the String body handlers.
> Or for the response headers to be returned first, then the body pulled,
> i.e.
> through an InputStream for example.
>
> While standardising in JDK 11, we’ve updated the javadoc to make this
> more clear, as well as adding other pull handlers. Additionally, a custom
> handler can be written, with a little extra work, to inspect headers, etc,
> before reading the body. Such a handle will be delivered all the response
> data before any potential error.
>
> -Chris.



-- 
Simon Roberts
(303) 249 3613
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/net-dev/attachments/20180515/d7793a25/attachment-0001.html>


More information about the net-dev mailing list