users@jax-rs-spec.java.net

[jax-rs-spec users] [jsr339-experts] Re: Re: Re: Re: Allowing two resources to be mapped to the same URI

From: Bill Burke <bburke_at_redhat.com>
Date: Wed, 23 May 2012 09:58:33 -0400

On 5/23/12 6:16 AM, Marek Potociar wrote:
>> REST has nothing to do with Java type system. The same URI may have different representations. Different representations may require different Java types. Finally, entity providers aren't always the best solution to the problem.
>
> That's why we have support for multiple java methods processing the same HTTP method right? And everything about the same resource remains nicely encapsulated in a single class.
>

You're missing my point. Your solution to many of the problems I listed
was, "use an entity provider". Using an entity provider isn't always a
possibility.

> Well for me the matching does not involve just matching the URI. In the matching process you are doing lots of complex processing in any of these phases:
>
> 1. match URI
> 2. match HTTP method
> 3. match consumed/produced media types
>
> If any of the phases requires stepping a level up, for me it is a back tracking. The point of the current matching algorithm is exactly to avoid the need for doing that. In Jersey we also use the approach that URI matching in phase 1 produces a list of methods that are further filtered in phases 2& 3. Same as in your impl, it does not matter what class the method belongs to (which is why I said in the beginning that it is not a problem for us to support the issue implementation-wise). However, if there is no method found after phase 1, 2& 3 are finished, we do not back-track and repeat the same process with another resource URI in the list. And that's also something I don't want to be forced to do.
>

FWIW:

we break up @Path mappings into segments and map those segments onto a
tree structure. Any expression ends the segmentation. When a URI comes
in, we segment the URI and do a depth first search on this tree.

1. If there's a completely static path that matches the URI we check
HTTP method and consumed/produced.
2. If there's none, at that tree node, we try to match any expressions.
  If one matches, we check HTTP method/consumed produces
3. Then, we look at locators. If any match, we just return this locator
to be invoked on. This ends the lookup unfortunately.
4. If none match, we recurse back up the tree and try again at each
level. So we do backtrack, but not for locators.



Well, it would be very sad that for those of us that have superior
matching algorithms than the specification which support more use cases
would have to revert to something that's inferior.

Change the algorithm to be resource-method pattern based:

1. Create list of match expressions:

   a) For all resource methods, create a match expression by
concatenating the class's @Path expression to the resource method's
@Path expression and add to list
   b) For all locators append ".*" to the expression
   c) Sort this list preceding number of literal characters as primary
key(descending), number of matching groups as secondary(ascending) and
locator produced expressions as the teritary key (descending)

So, fully literal expressions take precendence over matching group
patterns. Resource methods take precendence over resource locators.
Implementations are allowed to weed out expressions that could never
match to optimize matching performance.

2. Perform match
  for each expression
    a. match URI
    b. If locator is matched, goto step 1 and match based on remaining path
    c. Match HTTP method
    d. Match produces/consumes
    e. If all criteria match, then you are good to go.

3. If there is an expression that matches the URI, but not the method,
do the 405 thing as defined currently in the spec
4. If there is an expression that matches the URI and the method, but
not the Accept type, do the 415 as expression in the current spec.

You could reduce the complex, hard to understand 2 page pseudo code,
with something much simpler that covers more use cases. You'd be hard
pressed to figure out whether my above algorithm is backward compatible
considering the complexity of the original, so I doubt you'd ever
consider this...

BTW, I think it would be very wrong for the TCK to test the 405/415 edge
cases. Implementations should be able to support this type of matching.
  What's more important for the TCK is to test the case where you have
multiple matches and the choice of that match.

Hey, in any case, if you do add some ridiculous TCK test for this, I
reserve the write to send you a hate email every time some user
complains that old code doesn't work any more because we had to change
our matching algorithm.


-- 
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com