jsr356-experts@websocket-spec.java.net

[jsr356-experts] Re: Dynamic Path matching

From: Joe Walnes <joe_at_walnes.com>
Date: Sat, 15 Sep 2012 16:27:16 -0500

I echo most of Mark's opinions, with one difference...

I'd give a +1 to suggestion 3. I've seen this pattern used frequently. e.g.
/stream/newsfeed/{category}.

However, I would pass the path parameters to the @WebSocketOpen call as
it's the kind of thing you care about at connection time, rather than each
individual message.

On Sat, Sep 15, 2012 at 10:52 AM, Mark Thomas <mark_at_homeinbox.net> wrote:

> On 15/09/2012 00:43, Danny Coward wrote:
> > Hi folks,
> >
> > Wanted to get your input on a few ideas to do with more flexible path
> > matching. Currently in the API, the endpoint by default gets matched on
> > the URI for an opening handshake using an exact match with the URI used
> > to register it. And the developer can override this behavior with
> > whatever matching criteria they want to.
> >
> > But for the developer using annotations, I wanted to explore the options
> > for something more flexible than just exact match on the path()
> > attribute of the class-level @WebSocketEndpoint annotation. It would
> > allow POJOs to map more flexibly in the URL space, could be useful for
> > developers (especially to javascript clients).
> >
> > Here are a few directions to look at (some inspired by servlet and
> > JAX-RS schemes):-
> >
> > 0) Re-use the servlet concept of url-patterns
> >
> > In this case, the path() attribute on the @WebSocketEndpoint annotations
> > would be able to contain servlet url-patters, matching defined as in the
> > servlet spec, for example:-
> >
> > @WebSocketEndpoint(path="/club") - endpoint matches /club only
> > @WebSocketEndpoint(path="/club/*") - endpoint matches anything beginning
> > /club
> > @WebSocketEndpoint(path="/club/*.websocket") - endpoint matches anything
> > ending .websocket
> I hope you mean path="*.websocket" here.
>
> +1 otherwise
>
> > 1) Allow method level annotations to define subpaths.
> >
> > Here, the class level @WebSocketEndpoint defines a path, as it does now.
> > But, for example @WebSocketMessage could add a subpath in order to match
> > only on the aggregate path. For example,
> >
> > @WebSocketEndpoint(path="/club")
> > public class Bar {
> >
> > @WebSocketMessage(subpath="/normal-people")
> > public void takeOrder(String orderString, Session session) {
> > // called from websocket clients who connected to
> > /club/normal-people
> > // yeah, we'll get to you when we get to you
> > }
> >
> > @WebSocketMessage(subpath="/vips")
> > public void takeExpressOrder(String orderString, Session session) {
> > // called from websocket clients who connected to /club/vips
> > // ice and lemon ?
> > }
> > }
>
> -0
>
> I can see what you are getting at but I'd prefer to see two classes
> (with a common base class) mapped to the separate end points.
>
> In the case above:
> - Where do messages for the "/club" endpoint get routed?
> - Is it even valid to connect to the "/club" endpoint?
> - What if users don't went "/club" to be a valid endpoint?
>
> This option appears to adds a lot of potential complexity and corner
> cases. These all need to be carefully thought through and the required
> behaviour clearly specified. On a first look I'm not convinced that work
> is work the effort (although I'm prepared to be convinced otherwise).
>
> > 2) Allow regular expressions in the URI paths
>
> -1
>
> This is a bad idea. It creates a mapping ambiguity when multiple regular
> expressions match a request. I am strongly against this.
>
> > 3) Allow a kind of path templating, where path segments may be used in
> > web socket code.
> >
> > Here, the kind of URIs allowed in the @WebSocketEndpoint path()
> > attribute could include variable path segments, where the variables can
> > be passed as parameters (annotated with a new @PathParam annotation)
> > into the methods on the POJO later.
> >
> > @WebSocketEndpoint(path="/club/{member-level}/{member-name}")
> > // means this POJO is an endpoint for all URLs that begin with "/club"
> > public class Bar {
> > @WebSocketMessage
> > public void takeOrder(String orderString,
> > @PathParam(id="member-level") String mLevel,
> > @PathParam(id="member-name") String mName, Session session) {
> > if ("vip".equals(mLevel)) {
> > // "Good evening, " + nName + " I have your drink already
> > prepared."
> > } else {
> > // wait your turn mate
> > }
> > }
> > }
>
> +0
>
> I could easily be convinced to be +1 if there was a user demand for
> this. I haven't seen it yet but it is still early days for the WebSocket
> users in Tomcat.
>
> > I think in general one, or some hybrid of two of these four approaches
> > would be a good addition to the model. The servlet one (0) may be well
> > understood, but doesn't seem as useful as 2) or 3). Clearly all four
> > would be overkill.
> >
> > I'd be interested to know your thoughts on these approaches.
>
> In summary:
> 0) Yes
> 1) Maybe, but it looks like a lot of work
> 2) No way
> 3) Yes, if there is a demand for it
>
> Mark
>
>