users@jax-rs-spec.java.net

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

From: Sergey Beryozkin <sberyozkin_at_talend.com>
Date: Fri, 16 Oct 2015 15:31:00 +0100

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:
>
> http://bill.burkecentral.com/2013/05/29/the-poor-jax-rs-request-dispatching-algorithm/
>
>
> 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 [mailto:bburke_at_redhat.com]
>> Sent: Donnerstag, 15. Oktober 2015 15:52
>> To: jsr370-experts_at_jax-rs-spec.java.net
>> 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 <sberyozkin_at_talend.com>
>>>> 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 [mailto:sberyozkin_at_talend.com]
>>>>> Sent: Montag, 12. Oktober 2015 22:33
>>>>> To: jsr370-experts_at_jax-rs-spec.java.net
>>>>> 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
>>>>>>> <markus_at_headcrashing.eu> 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 [mailto:sberyozkin_at_talend.com]
>>>>>>> Sent: Montag, 12. Oktober 2015 17:26
>>>>>>> To: jsr370-experts_at_jax-rs-spec.java.net
>>>>>>> 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 3.7.2.2.e: "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
>>>>>>>>> <sberyozkin_at_talend.com>
>>>>>>> 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
>>>>>>>>>>>> (https://java.net/jira/browse/JERSEY-2942) 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
>>>>>>>>>>>>
>>>>>
>>>>
>>>
>>
>