[jsr356-experts] Re: Dynamic Path matching

From: Mark Thomas <mark_at_homeinbox.net>
Date: Sat, 15 Sep 2012 16:52:37 +0100

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 ?
> }
> }


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


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
> }
> }
> }


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