Hi Anthony, thanks a lot for looking into this! > On 3 Apr 2016, at 17:45, Anthony Vanelverdinghe > <anthony.vanelverdin...@gmail.com> wrote: > > Here are my suggestions concerning the public types: > > java.net.http.WebSocket > - order the arguments of > static Builder newBuilder(URI uri, HttpClient client, Listener listener) > consistently with the 2-argument method: > static Builder newBuilder(URI uri, Listener listener, HttpClient client)
I see your concern. I've considered using the same signature. But I chose the other one for a reason. There are pros and cons for both versions, of course. If we choose the proper telescoping version newBuilder(URI uri, Listener listener, HttpClient client) then it would be more consistent with the 2-arg method indeed. On the other hand it would make a use of an in-place created Listener a bit more ugly. Imagine a huge anonymous "listener" in the middle with an almost unnoticeable tiny "client" in the end of the argument list: WebSocket.newBuilder(URI.create("ws://myws"), new Listener() { @Override public void onOpen(WebSocket webSocket) { ... } ... @Override public CompletionStage<?> onPong(WebSocket webSocket, ByteBuffer message) { ... } }, client); I would prefer to have something extensible moved to the very end of the list of arguments. But that's just my opinion. > - remove CompletableFuture<Void> sendText(Stream<? extends CharSequence> > message): > there are many candidate convenience methods, and the choice for Stream<? > extends CharSequence> seems arbitrary. For example, why this one, and not > methods with char[] (analog to the byte[] method for sendBinary), Iterable<? > extends CharSequence> (as used by java.nio.file.Files::write), Reader, ... java.util.stream.Stream would be a more general source than java.lang.Iterable. > convenience methods can always be added in a later version, based on > empirical evidence of which convenience methods would add most value Absolutely! > - remove CompletableFuture<Void> sendBinary(byte[] message, boolean isLast): > same motivation as the previous one > > - add CompletableFuture<Void> sendBinary(ByteBuffer message) > to be consistent with sendText, which has the single-parameter method > sendText(CharSequence message) I will think about it. > - CompletableFuture<Void> sendClose(CloseCode code, CharSequence reason) > change the type of "reason" to String What's the rationale behind this? > java.net.http.WebSocket.Builder > - Builder connectTimeout(long timeout, TimeUnit unit) > use a single java.time.Duration argument instead I'm not too familiar with the new java.time API, but maybe you could explain what would some advantages be over the java.util.concurrent one? The one I can think of immediately is the encapsulation and consistency check would be done by java.time rather than by java.net.http.WebSocket. On the other hand java.util.concurrent.TimeUnit is more familiar. > java.net.http.WebSocket.Listener > - onText/onBinary/onPing/onPong > return an immediately-complete CompletionStage (i.e. > CompletableFuture.completedStage(null)) instead of null We've been through this. It's a matter of both performance AND convenience. A user gets both convenience of returning null and reduction of allocation. Moreover if we go with disallowing null, people might be tempted to use a single shared instance CompletableFuture.completedStage(null) as a return value. I'd better stay away from it (though it seems technically possible, it still feels hacky). > return CompletionStage<Void> instead of CompletionStage<?> I thought about this and discarded previously. The reason is simple. It would kill the simple composability, when one could easily return a CS<what-have-you> from any of the onXXX methods. Because CS<what-have-you> can always be assigned to CS<?>. Once again, it's a convenience to the user. > - onText > change the type of the "message" parameter with ByteBuffer, and specify it > contains UTF-8 encoded bytes & has a backing array > > java.net.http.WebSocket.Text > remove this interface. I believe the Text interface doesn't carry its weight. > By specifying the Listener::onText method as above, one can easily do > something like new String().getBytes(message.array(), UTF_8) to get a > CharSequence Interesting. You're willing to give away this thing. May I ask why? First of all, in today's realities backing array would simply mean that the ByteBuffer is not direct, and since data from the SocketChannel is read into direct buffers _internally_ , it would mean that you've got a copy. Would you like your data to be unconditionally copied every time? Secondly, WebSocket Text messages may arrive in fragments, which guaranteed to be proper UTF-8 sequences only after fully assembled. So a fragment may arrive as an _incomplete_ UTF-8 sequence and the new String().getBytes(message.array(), UTF_8) wouldn't do. So if we remove this, then it means each and every user will have to deal with all sorts of lovely character issues by themselves. Now, as an implementor, I would be more than happy to unload this burden from myself :-) To be honest that's the most troublesome piece of code so far. But what about users? If you want the implementation to reshape the buffers so that they contain only proper sequences, then the implementation will have to parse & buffer the incoming stream. Given that it already does this (parsing) for the sake of verification required by the spec, wouldn't it be nice to provide characters as a by-product so the user won't have to bother? > java.net.http.WebSocketHandshakeException > - extend IOException, consistently with all other exception classes in > java.net and javax.net I will think about it. > - if HttpResponse can indeed be null (as is documented in getResponse), the > constructor's current implementation will throw a NullPointerException in > this case The reason is simple: Serialization. All exceptions must be serializable. But that's just a corner case. I will add the comment to the javadoc as was suggested previously by Joe Darcy: /** * Returns a HTTP response from the server. * -> * <p> The value may be unavailable ({@code null}) if this exception has -> * been serialized and then read back in. * * @return server response */ Thanks!