users@jax-rs-spec.java.net

[jax-rs-spec users] [jsr339-experts] Re: Re: Re: Re: Re: Re: Fwd: [Resteasy-users] PostProcessInterceptors not invoked for responses created by ExceptionMappers

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Thu, 23 Aug 2012 16:33:48 +0200

On Aug 23, 2012, at 2:47 PM, Santiago Pericas-Geertsen <santiago.pericasgeertsen_at_Oracle.com> wrote:

>
> On Aug 23, 2012, at 8:23 AM, Marek Potociar wrote:
>
>>
>> On Aug 22, 2012, at 9:22 PM, Santiago Pericas-Geertsen <santiago.pericasgeertsen_at_Oracle.com> wrote:
>>
>>>
>>> On Aug 22, 2012, at 11:59 AM, Bill Burke wrote:
>>>
>>>> Maybe this might simplify things?
>>>>
>>>> If exception thrown from resource method
>>>> - ExceptioMapper
>>>> - response filters and interception if there is an entity.
>>>>
>>>> If an exception thrown in response filter (or WriterInterceptor)
>>>> - ExceptionMapper
>>>> - no additional filtering or interception.
>>>
>>> How about this variation? Exception in:
>>>
>>> (1) Pre-match request filter or Response filter or Writer Interceptor
>>> -> Exception Mapper -> Response
>>>
>>> (2) Post-match request filter or Resource method or Reader interceptor
>>> -> Exception Mapper -> Response chain -> Response
>>
>> Why is reader interceptor different?
>
> Than the writer interceptor? A writer interceptor will be called after the response chain, if it throws an exception, it seems unnecessary to do the response chain again.

Why? The exception might be mapped to a new Response instance. That response instance should be treated as any other response instance. Also, why the treatment of WriterInterceptor should be different from MBW or any other provider? According to the spec, if a provider throws an exception, it's essentially treated the same way as if the exception has been thrown by a resource method (see section 4.5).

>
>>
>>> Notes:
>>>
>>> - If abortWith(Response) called in pre-match then (1)
>>
>> Why should abortWith(Response) be treated differently for this case? FWIW, in Jersey we have not seen ANY use case where a response filter would require resource information. I'm not saying there are no such use cases. Yet from our experience response filters deal almost exclusively with response headers or entity. So I'd say that global response filters should be applied to abort response in all cases.
>>
>>>
>>> - If abortWith(Response) called in post-match then (2)
>
> I propose to treat abortWith() just like producing a response from a mapped exception. So it follows the rules for (1) and (2) depending on where it is called.

I see. In that case I'd argue that we should specify that global response filters should be applied to ANY response.

>>>
>>> - Writer interceptors executed after Exception Mapper
>>
>> So if executed BEFORE any exception mapping, the exception thrown from a writer interceptor and mapped to a response would still be filtered?
>
> No, because it falls into case (1) above.

Again, I disagree that exceptions from MBW and from WriterInterceptors should be treated differently.

>
>>>
>>> - At most one Exception Mapper can be used per request/response (no loops)
>>
>> What does that mean? E.g. in case (2), what if the second exception is thrown in the response chain? Wouldn't it get mapped to a response?
>
> This means an exception thrown while processing a _mapped_ response is not mapped again (it's propagated to the container).

Ok, that's in line with what the spec says at the moment IIUC.

>
>>>
>>> - No such thing as pre-match response filter
>>
>> For the reasons explained above I'd more agree with a concept of no such thing as "post-matching" global response filters. IOW, global response filters should be invoked for any response regardless of whether the request has been matched or not.
>>
>> To clarify: by global I mean not name-bound and not dynamically bound. (From previous Jersey experience I would apply the same to request filters too - see my reasoning in my reply to Bill's email.)
>
> OK, let me read the other e-mail to get more context on this.

Btw. I'm starting to think that perhaps we should really leave things as they are specified now, just clarify the processing of a mapped exceptions. IOW:

an exception is mapped only once per a single request-response processing cycle (to prevent exception mapping loops)
any exception thrown while processing a response created as a result of previous exception mapping is treated as "unmapped", i.e. it is propagated to the hosting IO container
a response created from a mapped exception is run through the response filter chain that is constructed based on a given processing context. I.e. if a resource has been matched, then all response filters applicable to the resource would be invoked; if a resource has not been matched yet, only global response filters would be invoked.

The above would ensure that all exceptions - from resources as well as from providers - are treated consistently. Any subsequent exceptions would be then treated consistently too.

Marek

>
> -- Santiago
>