users@websocket-spec.java.net

[jsr356-users] [jsr356-experts] Re: Re: V003 API for your review

From: Greg Wilkins <gregw_at_intalio.com>
Date: Sat, 11 Aug 2012 12:23:46 +1000

On 10 August 2012 09:57, Danny Coward <danny.coward_at_oracle.com> wrote:

> Also for ease of use, I'd really like to see the API offer message
> aggregation as part of the API. With annotations this could be:
>
> @WebSocketEndPoint(maxMessage=8192)
> public class MyPojoWebSocket
> {
> @WebSocketMessage
> public void myAsyncTextHandler(String part)
> { ... }
> }
>
> Does this mean that the 'part' variable passed in would be the size of the
> message if less than 8192 bytes in length, otherwise the first 8192 bytes
> of the message ?
>
> Interesting. What kind of use case are you thinking of ?
>


If you are writing an application where you know your maximum message size
(eg for chess.com we know exactly the size of a move or a representation of
the chess board).
Because these messages are small (typically 10s of bytes) then if we code
to the API

  public void myAsyncTextHandler(String part, boolean last)

we will almost almost always receive the messages in a single callback with
all the bytes and last==true. This could result in lazy programmers
assuming that "almost always" == "always" and not handle the case where
last==false. There code would mostly work until somebody deploys some
evil proxy that fragments all frames into 1 byte messages... or similar
strange stuff. This will break code that has assumed last==true always.

That I think we should allow users to delegate aggregation of the parts to
the protocol handling so they can just implement

  public void myAsyncTextHandler(String completeMessage)

But to do so, they need to tell the protocol handling what is the max
message size they expect, so that if any parts add up to more than that,
that is an error - close the connection etc.



with neither being blocking. The user simply needs to call
> sendBytes(data).get() to achieve blocking.
>
> Alternately if you want to keep the blocking call, then don't have a
> future in the API at all. Instead provide a utility implementation of
> SendHandler that is a Future and can be used like:
>
> SendHandlerFuture future=new SendHandlerFuture();
> wsEndPoint.sendBytes(data,future);
> future.get(10,TimeUnit.SECONDS);
>
> This mantra could easily be wrapped up in a static method to make it a one
> liner:
>
> SendHandlerFuture.sendBytes(wsEndPoint,data).get(10,TimeUnit.SECONDS);
>
> Yeah, I agree combining the byFuture and the byCompletion version into
> one method is neither typical nor efficient if you don't use the future,
> even if its compact. Probably should separate them out.
> I do think that the blocking version is going to be the easy/70% kind of
> style that developers would use. So I think it ought to be as simple as
> possible - i.e. only one method call.
> Maybe we should just have 3 calls for the three styles: blocking,
> byFuture, byCompletion, nice and explicit and no extra steps needed ?
>


I'm ok with either:

1 method (async callback only with future/blocking provided by a
SendHandlerFuture)
2 methods (async callback and one returning future - just like NIO.2)
3 methods (async callback, return future, blocking)

but with a slight preference for 1, then 2, then 3

cheers




-- 
Greg Wilkins <gregw_at_intalio.com>
http://www.webtide.com
Developer advice and support from the Jetty & CometD experts.