java.net.http.HttpClient: invalid exception when bad status line is returned

2019-01-18 Thread Dmitry Sivachenko
Hello, 

I am tasting java.net.http.HttpClient with  

openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.1+13)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.1+13, mixed mode)

on Mac OS X 10.14.2.

Consider the case when server responds with bad (invalid format) status line: 
"HTTP/1.1 FOO"

The following IllegalArgumentException is thrown:

Exception in thread "main" java.lang.IllegalArgumentException: For input 
string: "FOO"
at 
java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:551)
at 
java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:119)
at ru.mitya.test.App.main(App.java:14)
Caused by: java.lang.NumberFormatException: For input string: "FOO"
at 
java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at 
java.net.http/jdk.internal.net.http.Http1HeaderParser.readStatusLineFeed(Http1HeaderParser.java:197)
at 
java.net.http/jdk.internal.net.http.Http1HeaderParser.parse(Http1HeaderParser.java:124)
at 
java.net.http/jdk.internal.net.http.Http1Response$HeadersReader.handle(Http1Response.java:672)
at 
java.net.http/jdk.internal.net.http.Http1Response$HeadersReader.handle(Http1Response.java:603)
at 
java.net.http/jdk.internal.net.http.Http1Response$Receiver.accept(Http1Response.java:594)
at 
java.net.http/jdk.internal.net.http.Http1Response$HeadersReader.tryAsyncReceive(Http1Response.java:650)
at 
java.net.http/jdk.internal.net.http.Http1AsyncReceiver.flush(Http1AsyncReceiver.java:228)
at 
java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
at 
java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
at 
java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
at 
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at 
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)


instead of the expected ProtocolException:

Exception in thread "main" java.io.IOException: Invalid status line: "HTTP/1.1 
FOO"
at 
java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:565)
at 
java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:119)
at ru.mitya.test.App.main(App.java:14)
Caused by: java.net.ProtocolException: Invalid status line: "HTTP/1.1 FOO"
<...>

The suggested fix would be to catch IllegalArgumentException thrown by 
Integer.parseInt() in readStatusLineFeed() and throw 
ProtocolException instead of it.

What do you think?

Thanks.

Here is a sample test program:

package ru.mitya.test;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class App {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newBuilder().build();
HttpRequest req = 
HttpRequest.newBuilder(URI.create("http://localhost:8000/";))
.version(HttpClient.Version.HTTP_1_1)
.build();
HttpResponse resp = client.send(req, 
HttpResponse.BodyHandlers.ofString());
}
}



Re: [13] RFR: 8216561: HttpClient: The logic of retry on connect exception is inverted

2019-01-18 Thread Andrej Golovnin
Hi Daniel,

> Right - here is a better implementation anyway:
> http://cr.openjdk.java.net/~dfuchs/webrev_8216561/webrev.02/
> 

Looks much better. Thanks a lot!

Best regards,
Andrej Golovnin



Re: [13] RFR: 8216561: HttpClient: The logic of retry on connect exception is inverted

2019-01-18 Thread Chris Hegarty

On 18/01/2019 14:24, Daniel Fuchs wrote:

Hi Andrej,

On 18/01/2019 14:03, Andrej Golovnin wrote:
Is creating new Optionals a real problem? And before you answer please 
remember what Donald Knuth said: The real problem is that programmers 
have spent far too much time worrying about efficiency in the wrong 
places and at the wrong times; premature optimization is the root of 
all evil (or at least most of it) in programming. ;-)


Right - here is a better implementation anyway:
http://cr.openjdk.java.net/~dfuchs/webrev_8216561/webrev.02/


This looks good Daniel.

-Chris.


Re: [13] RFR: 8216561: HttpClient: The logic of retry on connect exception is inverted

2019-01-18 Thread Daniel Fuchs

Hi Andrej,

On 18/01/2019 14:03, Andrej Golovnin wrote:
Is creating new Optionals a real problem? And before you answer please 
remember what Donald Knuth said: The real problem is that programmers 
have spent far too much time worrying about efficiency in the wrong 
places and at the wrong times; premature optimization is the root of all 
evil (or at least most of it) in programming. ;-)


Right - here is a better implementation anyway:
http://cr.openjdk.java.net/~dfuchs/webrev_8216561/webrev.02/

best regards,

-- daniel


Best regards and have a nice weekend,
Andrej Golovnin




Re: RFR: 8207404: MulticastSocket tests failing on AIX

2019-01-18 Thread Chris Hegarty



On 18/01/2019 08:54, Langer, Christoph wrote:

Hi,

here is the updated webrev with modifications to the problem list and 
reverting the static imports: 
_http://cr.openjdk.java.net/~clanger/webrevs/8207404.1/__

I think this is ok.

-Chris.


Re: [13] RFR: 8216561: HttpClient: The logic of retry on connect exception is inverted

2019-01-18 Thread Andrej Golovnin
Hi Daniel,

Yes that looks like my first implementation. But then
> I reflected that avoiding to map Optional to Duration
> and then back to a new Optional containing the same
> duration could be avoided by simply storing the original
> optional obtained from the HttpClient.
>
> The current code only creates a new instance of Optional
> when it needs to.
>

Is creating new Optionals a real problem? And before you answer please
remember what Donald Knuth said: The real problem is that programmers have
spent far too much time worrying about efficiency in the wrong places and
at the wrong times; premature optimization is the root of all evil (or at
least most of it) in programming. ;-)

Best regards and have a nice weekend,
Andrej Golovnin


Re: [13] RFR: 8216561: HttpClient: The logic of retry on connect exception is inverted

2019-01-18 Thread Daniel Fuchs

Hi Andrej,

Yes that looks like my first implementation. But then
I reflected that avoiding to map Optional to Duration
and then back to a new Optional containing the same
duration could be avoided by simply storing the original
optional obtained from the HttpClient.

The current code only creates a new instance of Optional
when it needs to.

best regards,

-- daniel

On 18/01/2019 12:42, Andrej Golovnin wrote:

Hi Daniel,

webrev:
http://cr.openjdk.java.net/~dfuchs/webrev_8216561/webrev.01/



  126     private static class ConnectTimeoutTracker {
  127         final Optional max;
  128         final AtomicLong startTime = new AtomicLong();
  129         ConnectTimeoutTracker(Optional connectTimeout) {
  130             this.max = connectTimeout;
  131         }
  132
  133         Optional getRemaining() {
  134             if (max.isEmpty()) return max;
  135             long now = System.nanoTime();
  136             long previous = startTime.compareAndExchange(0, now);
  137             if (previous == 0 || max.get().isZero()) return max;
  138             Duration remaining = 
max.get().minus(Duration.ofNanos(now - previous));

  139             assert remaining.compareTo(max.get()) <= 0;
  140             return Optional.of(remaining.isNegative() ? 
Duration.ZERO : remaining);

  141         }
  142
  143         void reset() { startTime.set(0); }
  144     }
An Optional in a class field or in a data structure, is considered a 
misuse of the API (see the explanation by Stuart Marks: 
https://stackoverflow.com/questions/23454952/uses-for-optional/23464794#23464794). 
I would write it this way:


       private static class ConnectTimeoutTracker {
           final Duration max;
           final AtomicLong startTime = new AtomicLong();
           ConnectTimeoutTracker(Duration connectTimeout) {
               this.max = connectTimeout;
           }
           Optional getRemaining() {
               return Optional.ofNullable(max)
                   .map(m -> {
                       long now = System.nanoTime();
                       long previous = startTime.compareAndExchange(0, now);
                       if (previous == 0 || m.isZero()) {
                           return m;
                       }
                       Duration remaining = m.minus(Duration.ofNanos(now 
- previous));

                       assert remaining.compareTo(m) <= 0;
                       return remaining.isNegative() ? Duration.ZERO : 
remaining;

                   });
           }
           void reset() { startTime.set(0); }
       }

Best regards,
Andrej Golovnin




RE: RFR: 8207404: MulticastSocket tests failing on AIX

2019-01-18 Thread Steve Groeger
Hi Christoph, 

Had a look at the latest webrev and everything looks OK to me.
Have also re-tested on my AIX systems and all tests oass OK.

Thanks
Steve Groeger
IBM Runtime Technologies
Hursley, Winchester
Tel: (44) 1962 816911  Mobex: 279990  Mobile: 07718 517 129
Fax (44) 1962 816800
Lotus Notes: Steve Groeger/UK/IBM
Internet: groe...@uk.ibm.com

Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number 
741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU



From:   "Langer, Christoph" 
To: Chris Hegarty , Steve Groeger 

Cc: "net-dev@openjdk.java.net" , 
"ppc-aix-port-...@openjdk.java.net" 
Date:   18/01/2019 08:54
Subject:RE: RFR: 8207404: MulticastSocket tests failing on AIX



Hi,
 
here is the updated webrev with modifications to the problem list and 
reverting the static imports: 
http://cr.openjdk.java.net/~clanger/webrevs/8207404.1/
 
It went fine through our test system so I think it’s good now.
 
Please review.
 
Thanks
Christoph
 
From: Chris Hegarty  
Sent: Donnerstag, 17. Januar 2019 12:27
To: Langer, Christoph 
Cc: net-dev@openjdk.java.net; ppc-aix-port-...@openjdk.java.net
Subject: Re: RFR: 8207404: MulticastSocket tests failing on AIX
 
 


On 17 Jan 2019, at 10:55, Langer, Christoph  
wrote:
 
Hi,
 
here is a fix for the MulticastSocket tests failing on AIX (in certain 
sceanrios):
 
Webrev: http://cr.openjdk.java.net/~clanger/webrevs/8207404.0/
 
Why remove the static imports from NetworkConfiguration? It makes
the code more verbose ( and IMO harder to read ).
 
-Chris.
 


Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number 
741598. 
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU



Re: [13] RFR: 8216561: HttpClient: The logic of retry on connect exception is inverted

2019-01-18 Thread Andrej Golovnin
Hi Daniel,

> webrev:
> http://cr.openjdk.java.net/~dfuchs/webrev_8216561/webrev.01/
>
>
>
 126 private static class ConnectTimeoutTracker {
 127 final Optional max;
 128 final AtomicLong startTime = new AtomicLong();
 129 ConnectTimeoutTracker(Optional connectTimeout) {
 130 this.max = connectTimeout;
 131 }
 132
 133 Optional getRemaining() {
 134 if (max.isEmpty()) return max;
 135 long now = System.nanoTime();
 136 long previous = startTime.compareAndExchange(0, now);
 137 if (previous == 0 || max.get().isZero()) return max;
 138 Duration remaining = max.get().minus(Duration.ofNanos(now
- previous));
 139 assert remaining.compareTo(max.get()) <= 0;
 140 return Optional.of(remaining.isNegative() ? Duration.ZERO
: remaining);
 141 }
 142
 143 void reset() { startTime.set(0); }
 144 }

An Optional in a class field or in a data structure, is considered a misuse
of the API (see the explanation by Stuart Marks:
https://stackoverflow.com/questions/23454952/uses-for-optional/23464794#23464794).
I would write it this way:

  private static class ConnectTimeoutTracker {
  final Duration max;
  final AtomicLong startTime = new AtomicLong();
  ConnectTimeoutTracker(Duration connectTimeout) {
  this.max = connectTimeout;
  }

  Optional getRemaining() {
  return Optional.ofNullable(max)
  .map(m -> {
  long now = System.nanoTime();
  long previous = startTime.compareAndExchange(0, now);
  if (previous == 0 || m.isZero()) {
  return m;
  }
  Duration remaining = m.minus(Duration.ofNanos(now -
previous));
  assert remaining.compareTo(m) <= 0;
  return remaining.isNegative() ? Duration.ZERO :
remaining;
  });
  }

  void reset() { startTime.set(0); }
  }

Best regards,
Andrej Golovnin


[13] RFR: 8216561: HttpClient: The logic of retry on connect exception is inverted

2019-01-18 Thread Daniel Fuchs

Hi,

Please find below a small fix for:

8216561: HttpClient: The logic of retry on connect exception is inverted
https://bugs.openjdk.java.net/browse/JDK-8216561

webrev:
http://cr.openjdk.java.net/~dfuchs/webrev_8216561/webrev.01/

The patch now allows retry on connect exception, ensuring
that the second attempt takes into account the time spent
in the first attempt in order to honor the connect timeout
value (if present).

best regards,

-- daniel


RE: RFR: 8207404: MulticastSocket tests failing on AIX

2019-01-18 Thread Langer, Christoph
Hi,

here is the updated webrev with modifications to the problem list and reverting 
the static imports: http://cr.openjdk.java.net/~clanger/webrevs/8207404.1/

It went fine through our test system so I think it's good now.

Please review.

Thanks
Christoph

From: Chris Hegarty 
Sent: Donnerstag, 17. Januar 2019 12:27
To: Langer, Christoph 
Cc: net-dev@openjdk.java.net; ppc-aix-port-...@openjdk.java.net
Subject: Re: RFR: 8207404: MulticastSocket tests failing on AIX




On 17 Jan 2019, at 10:55, Langer, Christoph 
mailto:christoph.lan...@sap.com>> wrote:

Hi,

here is a fix for the MulticastSocket tests failing on AIX (in certain 
sceanrios):

Webrev: http://cr.openjdk.java.net/~clanger/webrevs/8207404.0/

Why remove the static imports from NetworkConfiguration? It makes
the code more verbose ( and IMO harder to read ).

-Chris.