[jax-rs-spec users] Re: _at_Path with regular expression overrides other @Path's with the same URI

From: Sergey Beryozkin <>
Date: Tue, 20 Oct 2015 21:54:16 +0100

Besides that, the reason I like it is because it can offer a way toward
improving the algorithm, with the new ideas eventually pushed back into
the spec process based on the user experience, etc...

I agree with Bill we should try and get whatever is realistic to fix to
get fixed, but there has to be a way forward too, beyond the existing
algo text

Cheers, Sergey
On 20/10/15 21:49, Markus KARG wrote:
> Sergey,
> my proposal simply tries to provide a technically possible concensus among _all_ parties.
> I just do not see any other feasible solution to the original problem. And I do not share some experts' ideas to simply ignore the community's currrent problem and keep the incompatibility of the existing implementations.
> -Markus
> -----Original Message-----
> From: Sergey Beryozkin []
> Sent: Dienstag, 20. Oktober 2015 22:40
> To:
> Subject: Re: [jax-rs-spec users] @Path with regular expression overrides other @Path's with the same URI
> On 16/10/15 16:00, Bill Burke wrote:
>> I bet you can count on one hand the users that wanted plug in their
>> own matching strategy. Personally, I just can't justify that amount
>> of work just to satisfy a very small handful of users.
> So on one hand it is your unfounded bet based on exactly what ? On the
> other hand is a positive experience we've achieved in CXF with users
> being able to easily experiment with the matching algorithm.
> IMHO it would be a very useful feature to have, to be able to minimally
> affect the algo. The truth is, it is impossible to have a 100% perfect
> algorithm at the spec level
> Markus, see, I like this idea of yours :-)
> Sergey
>> Supporting backtracking allows support for some very simple use cases
>> that I get asked about all the time.
>> I've argued in the past that supporting backtracking does not break
>> backward compatibility. Marek and Santiago disagreed...Thus here we are.
>> On 10/16/2015 10:31 AM, Sergey Beryozkin wrote:
>>> Bill, I'd say it is a bit too strong.
>>> I've had many users in CXF successfully using a custom matching
>>> strategy, for example, before 2.0 spec improved the selection between
>>> multiple matching class resources on the same path, when choosing
>>> between multiple equal candidates based on a number of query/etc
>>> parameters, etc.
>>> I'm all for improving the algorithm. But I somehow suspect that a
>>> strategy path can make improving the algo more realistic as there will
>>> be a two-way link.
>>> Sergey
>>> On 16/10/15 15:13, Bill Burke wrote:
>>>> On 10/15/2015 5:09 PM, Markus KARG wrote:
>>>>> What about adding the ability for an application to provide a
>>>>> MatchingStrategyProvider?
>>>> I can't see anybody ever wanting to write one. So -1000.
>>>>> Like simply packing a POJO in the WAR file that is annotated by
>>>>> @Provider and implements any custom algorithm wanted? That way we
>>>>> could keep the spec as-is, and Bill and Sergey could simply wrap
>>>>> their existing "non-compliant but intuituve" algorithms as .class
>>>>> files, so developers can put that .class file into their WAR and have
>>>>> a WORA solution.
>>>>> Feasible?
>>>> -1000. Fix the spec. There's really no reason not to support
>>>> backtracking in the matching algorithm. It makes zero sense to
>>>> return 405 or 404 responses when there is a resource method that could
>>>> be matched by backtracking. Furthermore, it is highly doubtful that
>>>> backtracking would break existing Jersey apps as these apps don't rely
>>>> on backtracking. IMO, this change would be akin to adding a method to
>>>> an interface.
>>>> This simple program shows how silly the matching algorithm is:
>>>> @Path("/doc.txt")
>>>> @GET
>>>> @Path("/doc.pdf")
>>>> @GET
>>>> @Path("/{document}")
>>>> @DELETE
>>>> It is a well known best practice to use URLs rather than content
>>>> negotiation. Yet, in this simple program, the user would also have to
>>>> write explicit @DELETE methods for doc.txt and doc.pdf even though a
>>>> catch all would work just fine.
>>>> Here's some other ones too:
>>>> Resteasy changed its matching algorithm prior to the JAX-RS 2.0 TCK
>>>> specifically because users asked us to.
>>>>> -Markus
>>>>> -----Original Message-----
>>>>> From: Bill Burke []
>>>>> Sent: Donnerstag, 15. Oktober 2015 15:52
>>>>> To:
>>>>> Subject: Re: [jax-rs-spec users] @Path with regular expression
>>>>> overrides other @Path's with the same URI
>>>>> The right thing to do is to improve the matching algorithm. I could
>>>>> also refer you to a bunch of "bug" reports where people are
>>>>> complaining
>>>>> about the matching algorithm. I then have to explain to them that
>>>>> this
>>>>> isn't a "bug" but a "feature". I also must say that there are far
>>>>> fewer
>>>>> ISVs than regular JAX-RS developers that stick to one implementation.
>>>>> Changing the TCK for one edge case that may break 2 different products
>>>>> that are 7+ years old with thousands upon thousands of downloads
>>>>> doesn't
>>>>> sound like the best way to make Java EE developers happy.
>>>>> It is Jersey and the spec that should change. Changing the matching
>>>>> algorithm will in most cases effect no Jersey users.
>>>>> On 10/15/2015 8:11 AM, Marek Potociar wrote:
>>>>>> Hi Sergey,
>>>>>> Well, the discussion on the Jersey thread clearly shows how
>>>>>> confusing it is if the implementations are not 100% compliant with
>>>>>> the spec. You either are compliant or you are not. There are no
>>>>>> shades of gray when it comes to official spec compliance. If you
>>>>>> pass TCK, you are compliant, if you don’t you are not. If there is a
>>>>>> hole in TCK coverage, it may get fixed later and then you would need
>>>>>> to pass the fixed TCK to be compliant.
>>>>>> The standard specifications are here to ensure application
>>>>>> portability for users. From the user perspective a pure JAX-RS code
>>>>>> must behave the same way on ANY implementation that claims to be
>>>>>> JAX-RS compliant.
>>>>>> Marek
>>>>>>> On 15 Oct 2015, at 01:03, Sergey Beryozkin <>
>>>>>>> wrote:
>>>>>>> Hi Markus
>>>>>>> I'd like to refer to the other thread where you agreed we should
>>>>>>> not rush it.
>>>>>>> Yes, as it currently stands - RestEasy and CXF are not compliant in
>>>>>>> this specific case.
>>>>>>> However IMHO we should strive really hard not to treat such cases
>>>>>>> as this is how it should and that is it.
>>>>>>> I think it is more of a spec text being non-intentionally too
>>>>>>> strict in this case - lets give it a chance - if Santiago can find
>>>>>>> an opportunity to 'fix' it then we will all win, if not then at
>>>>>>> least we gave it another try
>>>>>>> Cheers, Sergey
>>>>>>> On 14/10/15 21:41, Markus KARG wrote:
>>>>>>>> Sergey,
>>>>>>>> I understand your arguments, but for users (and for TCK)
>>>>>>>> compliance is a true/false question. As an ISV I need to rely on
>>>>>>>> the fact that matching works exactly the same on all
>>>>>>>> implementations (at least as long the spec does not provide a
>>>>>>>> means for an application to provide its own matching algorithm).
>>>>>>>> So what do we tell people now? They wait for an answer. Are
>>>>>>>> CXF/RestEasy definitively non-compliant or not?
>>>>>>>> -Markus
>>>>>>>> -----Original Message-----
>>>>>>>> From: Sergey Beryozkin []
>>>>>>>> Sent: Montag, 12. Oktober 2015 22:33
>>>>>>>> To:
>>>>>>>> Subject: Re: @Path with regular expression overrides other @Path's
>>>>>>>> with the same URI
>>>>>>>> Hi Santiago
>>>>>>>> I was thinking on the way home, I thought the sentence where the
>>>>>>>> 'M' set is built from Rmatch = R(Td) is a bit strict.
>>>>>>>> I recall the explicit regular expressions were added at the last
>>>>>>>> moment in 1.0, the current text covers a situation with same verbs
>>>>>>>> OK (in that Jersey issue I thought there were two GETs where I'd
>>>>>>>> indeed expect the method with an explicit reg expression win)...
>>>>>>>> Rmatch = R(Td) condition blocks a GET method from being included
>>>>>>>> in M (referring to that example).
>>>>>>>> I suspect replacing a '=' symbol with another one implying Rmatch
>>>>>>>> is equal or equivalent to R(Td).
>>>>>>>> I suspect I might've got confused with my analysis above but I
>>>>>>>> open an issue
>>>>>>>> Markus, I'm not sure the fact CXF/Reasteasy would not select
>>>>>>>> DELETE makes either implementation broken :-).
>>>>>>>> My opinion the spec text is far from being perfect in this
>>>>>>>> specific case which I agree makes CXF/RestEasy is not compliant
>>>>>>>> here but perhaps in this case the spec text can be optimized
>>>>>>>> before a new TCK test is added :-).
>>>>>>>> Thanks, Sergey
>>>>>>>> On 12/10/15 19:22, Santiago Pericasgeertsen wrote:
>>>>>>>>>> On Oct 12, 2015, at 1:03 PM, Markus KARG
>>>>>>>>>> <> wrote:
>>>>>>>>>> Sergey,
>>>>>>>>>> so what is the conclusion now? CXF is broken and you will fix it?
>>>>>>>>> Let’s file it as an issue and review it later. I had a quick
>>>>>>>>> look at the algorithm and, frankly, it is not as clear as I hoped
>>>>>>>>> so but I don’t have the cycles to look at it deeper at this point.
>>>>>>>>> — Santiago
>>>>>>>>>> -----Original Message-----
>>>>>>>>>> From: Sergey Beryozkin []
>>>>>>>>>> Sent: Montag, 12. Oktober 2015 17:26
>>>>>>>>>> To:
>>>>>>>>>> Subject: Re: @Path with regular expression overrides other
>>>>>>>>>> @Path's
>>>>>>>>>> with the same URI
>>>>>>>>>> Hi Santiago
>>>>>>>>>> That long discussion we last had, that was related to a case
>>>>>>>>>> where a
>>>>>>>>>> matching subresource locator was discarded, even though it was
>>>>>>>>>> having
>>>>>>>>>> a matching method, as opposed to the current resource class.
>>>>>>>>>> It still 'hurts' whenever I think about it.
>>>>>>>>>> But in this case it is different, no backtracking of any sort is
>>>>>>>>>> even
>>>>>>>>>> needed here - it is so simple...
>>>>>>>>>> So we are at "Sort E using the number of literal
>>>>>>>>>> characters in each member as the primary key (descending order),
>>>>>>>>>> the
>>>>>>>>>> number of capturing groups as a secondary key (descending
>>>>>>>>>> order), the
>>>>>>>>>> number of capturing groups with non-default regular expressions
>>>>>>>>>> (i.e.
>>>>>>>>>> not
>>>>>>>>>> '([^/]+?)') as the tertiary key
>>>>>>>>>> (descending order)..."
>>>>>>>>>> Then yeah, DELETE is supposed to be selected. This is so sad. The
>>>>>>>>>> only consolation, regular expressions are not that popular...
>>>>>>>>>> Sergey
>>>>>>>>>> On 12/10/15 14:31, Santiago Pericasgeertsen wrote:
>>>>>>>>>>> All,
>>>>>>>>>>> First, obviously I agree the result is counter-intuitive.
>>>>>>>>>>> Second,
>>>>>>>>>>> we
>>>>>>>>>> have had this this discussion many in the times in the past
>>>>>>>>>> ;), and
>>>>>>>>>> basically the same algorithm since JAX-RS 1.0 AFAIK. Third, the
>>>>>>>>>> algorithm does not backtrack or look ahead, and thus makes a
>>>>>>>>>> decision
>>>>>>>>>> first on Path and then on method resulting in the observed
>>>>>>>>>> behavior
>>>>>>>>>> -because it discarded potential matches too soon.
>>>>>>>>>>> If an implementation behaves differently, it is because
>>>>>>>>>>> it is
>>>>>>>>>> implementing a different algorithm from the one in the spec.
>>>>>>>>>> Ideally
>>>>>>>>>> we should change the algorithm, but unfortunately it is not a
>>>>>>>>>> backward compatible change.
>>>>>>>>>>> - Santiago
>>>>>>>>>>>> On Oct 12, 2015, at 9:08 AM, Sergey Beryozkin
>>>>>>>>>>>> <>
>>>>>>>>>> wrote:
>>>>>>>>>>>> Oh, that is actually completely broken, I agree, I thought
>>>>>>>>>>>> there
>>>>>>>>>>>> were two
>>>>>>>>>> GET methods there, my fault.
>>>>>>>>>>>> I honestly can not see how that can be resolved as works as
>>>>>>>>>>>> expected...
>>>>>>>>>>>> Sergey
>>>>>>>>>>>> On 12/10/15 14:00, Bill Burke wrote:
>>>>>>>>>>>>> If this is true, then the matching algorithm is showing yet
>>>>>>>>>>>>> again,
>>>>>>>>>>>>> how
>>>>>>>>>> effed up it is. The @Get method in the example should always
>>>>>>>>>> resolve. It makes sense intuitively. In Resteasy if the @Delete
>>>>>>>>>> path
>>>>>>>>>> resolved first, but the methods didn't match, we would
>>>>>>>>>> "backtrack" and try the get method.
>>>>>>>>>>>>> On 10/11/2015 12:00 PM, Sergey Beryozkin wrote:
>>>>>>>>>>>>>> Jersey is correct in that example - a template var with a
>>>>>>>>>>>>>> regex
>>>>>>>>>>>>>> wins over a basic template var.
>>>>>>>>>>>>>> The spec clearly states that an expression with more literal
>>>>>>>>>>>>>> chars
>>>>>>>>>> wins.
>>>>>>>>>>>>>> So I guess a regex expression can only win if, besides the
>>>>>>>>>>>>>> rex-ex
>>>>>>>>>>>>>> expression itself, a given path has more literal chars, say,
>>>>>>>>>>>>>> abc[d|e] would win over abc - I think this can only happen
>>>>>>>>>>>>>> when
>>>>>>>>>>>>>> choosing between multiple matching root resources.
>>>>>>>>>>>>>> Or it can win in that Jersey JIRA issue - a number of literal
>>>>>>>>>>>>>> chars beyond the regex is equal but the regex method wins
>>>>>>>>>>>>>> because
>>>>>>>>>>>>>> a template var is more specific. I'll double check with
>>>>>>>>>>>>>> CXF - I
>>>>>>>>>>>>>> doubt it works
>>>>>>>>>> diff
>>>>>>>>>>>>>> in CXF
>>>>>>>>>>>>>> Sergey
>>>>>>>>>>>>>> On 11/10/15 08:28, Markus KARG wrote:
>>>>>>>>>>>>>>> Experts,
>>>>>>>>>>>>>>> in a discussion on the Jersey user group someone claimed
>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>> the behaviour of Jersey is different from CXF and
>>>>>>>>>>>>>>> RestEasy. As
>>>>>>>>>>>>>>> that would imply both, an inaccuracy of the TCK (it does not
>>>>>>>>>>>>>>> detect the
>>>>>>>>>>>>>>> deviation) and a violation of the specification in CXF and
>>>>>>>>>>>>>>> RestEasy (as Jersey is the RI, hence axiomatically cannot be
>>>>>>>>>>>>>>> wrong), we should quickly clarify the truth in that claim.
>>>>>>>>>>>>>>> The case is recorded in Jersey's issue tracker including
>>>>>>>>>>>>>>> source
>>>>>>>>>>>>>>> code
>>>>>>>>>>>>>>> ( and is simple to
>>>>>>>>>>>>>>> explain:
>>>>>>>>>>>>>>> *Given a resource has two methods, annotated as **_at_GET
>>>>>>>>>>>>>>> @Path(//<PathParam>/) and **_at_DELETE @Path(//<RegEx>/)*
>>>>>>>>>>>>>>> *When a client invokes **GET <RootURI>//<PathParam>/ upon
>>>>>>>>>>>>>>> that
>>>>>>>>>> resource*
>>>>>>>>>>>>>>> *Then the result is **405 Method Not Allowed*
>>>>>>>>>>>>>>> While this looks pretty odd to the average Joe (as there
>>>>>>>>>>>>>>> is a
>>>>>>>>>>>>>>> perfect match of GET and /<PathParam>/), it was claimed that
>>>>>>>>>>>>>>> this is _compliant_ to the specification (since regex have
>>>>>>>>>>>>>>> higher priority than literals, and methods are matched
>>>>>>>>>>>>>>> after URIs).
>>>>>>>>>>>>>>> It was reported that CXF and RestEasy return 200 OK instead,
>>>>>>>>>>>>>>> while the RI does return 405 Method Not Allowed.
>>>>>>>>>>>>>>> Certainly an application MUST return the same status code
>>>>>>>>>>>>>>> on ANY
>>>>>>>>>>>>>>> JAX-RS compliant implementations, so we should clarify ASAP
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> following questions:
>>>>>>>>>>>>>>> (1) @SpecLeads: Is the use case described above (regex beats
>>>>>>>>>>>>>>> literals) really compliant to the JAX-RS specification, and
>>>>>>>>>>>>>>> how
>>>>>>>>>>>>>>> to explain /to the average Joe/ the reasonability of
>>>>>>>>>>>>>>> ignoring
>>>>>>>>>>>>>>> the apparently perfect match?
>>>>>>>>>>>>>>> (2) @SpecLeads: Is there a bug in the TCK so it does not
>>>>>>>>>>>>>>> detect
>>>>>>>>>>>>>>> the deviation of CXF and RestEasy?
>>>>>>>>>>>>>>> (3) @Vendors: Can you please check your implementations
>>>>>>>>>>>>>>> whether
>>>>>>>>>>>>>>> they really violate the spec? Do you have plans to fix it?
>>>>>>>>>>>>>>> I think we all have a vital interest in clarifying it, as a
>>>>>>>>>>>>>>> standard makes only sense when it is reasonable and commonly
>>>>>>>>>>>>>>> accepted, so I would be glad if you could answer the above
>>>>>>>>>>>>>>> points rather soon. :-)
>>>>>>>>>>>>>>> Thanks
>>>>>>>>>>>>>>> -Markus