jsr339-experts@jax-rs-spec.java.net

[jsr339-experts] Re: [jax-rs-spec users] Re: Re: Need clarification on Section 6.7

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Fri, 1 Feb 2013 13:02:59 +0100

On Feb 1, 2013, at 12:55 PM, Sergey Beryozkin <sberyozkin_at_talend.com> wrote:

> On 01/02/13 11:38, Marek Potociar wrote:
>>
>> On Jan 31, 2013, at 6:29 PM, Sergey Beryozkin<sberyozkin_at_talend.com> wrote:
>>
>>> On 31/01/13 16:57, Marek Potociar wrote:
>>>> Hi Bill,
>>>> I'm forwarding my recent reply to a similar question we received from
>>>> TCK team:
>>>>
>>>> Global and globally name-bound filters and interceptors should be
>>>> invoked for all responses. Resource and method name-bound interceptors
>>>> should be invoked only for responses originated from the bound resource
>>>> or resource method.
>>>>
>>>> I.e. if we define 2 groups of filters and interceptors based on their
>>>> binding:
>>>>
>>>> G1: Global and globally name-bound (i.e. name-bound to the Application
>>>> sub-class) response filters and interceptors
>>>> - IMO the user intention with these is clearly to invoke them for ALL
>>>> responses
>>>>
>>>> G2: Resource and method name-bound response filters and interceptors
>>>> - IMO the user intention with these is to invoke them only for responses
>>>> originated from a particular resource or method
>>>>
>>>
>>> What are resource-bound filters, is it:
>>>
>>> @SomeName
>>> class MyFilter...
>>>
>>> @SomeName
>>> @Path("/root")
>>> public class RootResource {
>>> }
>>>
>>> Effectively MyFilter applies to all RootResource methods ?
>>
>> Yes, exactly.
>>
>>>
>>>> With the groups defined above, here's what I think it should work
>>>> (Santiago, please correct me if you think otherwise):
>>>>
>>>> UC1: Response returned from pre-matching filter:
>>>> - G1 gets invoked
>>>>
>>>> UC2: Response produced by an ExceptionMapper from an exception that
>>>> originated in a pre-matching filter:
>>>> - G1 gets invoked
>>>>
>>>> UC3: Response returned from post-matching filter:
>>>> - G2 + G1 gets invoked
>>>>
>>>> UC4: Response returned from matched resource method:
>>>> - G2 + G1 gets invoked
>>>>
>>>> UC5: Response produced by an ExceptionMapper from an exception that
>>>> originated in a matched resource method:
>>>> - G2 + G1 gets invoked
>>>>
>>>> UC6: Response produced by an ExceptionMapper from an exception that
>>>> originated in a response filter or interceptor processing a response to
>>>> a matched request:
>>>> - G2 + G1 gets invoked
>>>>
>>>> UC7: Response produced by an ExceptionMapper from an exception that
>>>> originated in a response filter or interceptor processing a response to
>>>> an unmatched request:
>>>> - G1 gets invoked
>>>>
>>>> Additionally, there is a condition in the spec that prevents infinite
>>>> loops for UC6 and UC7 (see 2nd paragraph in section 6.7 of the spec).
>>>> So, to sum-up, here's the conceptual algorithm I have in mind:
>>>>
>>>> start request processing
>>>> store G1 response filters and interceptors into the request context
>>>> try {
>>>> invoke pre-matching request filters
>>>> match request
>>>> if (request matched) {
>>>> store G2 response filters and interceptors into the request context
>>>> invoke global and bound post-matching request filters
>>>> invoke resource method
>>>> }
>>>> invoke all response filters stored to the request context
>>>> } catch (Exception ex) {
>>>> try {
>>>> map exception to response
>>>> invoke all response filters stored to the request context
>>>> } catch (Exception ex) {
>>>> propagate exception to the hosting container
>>>> }
>>>> }
>>>> exit request processing
>>>>
>>> I think it basically says that in Bill's (2) case all response filters are executed,
>>> What about his case 3 though, I think it is UC6, UC7 points, still not clear what if the mapped response has to run through remaining filters or not, for example,
>>>
>>> A->B, A throws the exception, is B still given a chance to handle the mapped response ?
>>
>> I thought the algorithm above is also clear on that. For a mapped exception response, ALL applicable response filters are invoked (not only "remaining ones"). So, both, A and B are invoked.
>>
>> FWIW, throwing an exception from a filter is IMO not the programming model we should optimize for. Such exceptions should mostly indicate that there is a problem with the filter implementation as such.
>>
>
> Hmm..., both A and B are response filters, they are processing some Response, A is first to process it and decides to throw an exception (intentionally) - what I don't quite get is whether it means we have an immediate 500, or, we try to map this A-originated exception and if the mapping was successful, then let B a chance to handle this mapped response, even though A thought it was an exception case...
>
> I'm sorry if I'm slow :-), but I'm still a bit unclear.

If A throws an exception that gets mapped, then both A and B will be invoked on the mapped response. If A throws an exception again, then the exception is going to be propagated to the hosting container.

Hope it's crystal clear now,
Marek

>
> thanks, Sergey
>
>> HTH,
>> Marek
>>
>>>
>>> Thanks, Sergey
>>>
>>>
>>>
>>>> HTH,
>>>> Marek
>>>>
>>>>
>>>> On Jan 30, 2013, at 4:29 PM, Bill Burke<bburke_at_redhat.com
>>>> <mailto:bburke_at_redhat.com>> wrote:
>>>>
>>>>> The section on filters and exception handling is unclear.
>>>>>
>>>>> if an exception is thrown from a resource method:
>>>>>
>>>>> 1. An exception mapper is found
>>>>> 2. bound and global filters are executed on the response
>>>>>
>>>>> If an exception is thrown from a request filter:
>>>>>
>>>>> 1. An exception mapper is found and executed
>>>>> 2. response filters are executed. BOund response filters only executed
>>>>> if this is not prematch
>>>>>
>>>>> If an exception is thrown from a response filter:
>>>>>
>>>>> 1. An exception maper is found and executed
>>>>> 2. ??? I assume no response filters are then executed?
>>>>> --
>>>>> Bill Burke
>>>>> JBoss, a division of Red Hat
>>>>> http://bill.burkecentral.com
>>>>
>>>
>>>
>>
>
>