users@jax-rs-spec.java.net

[jax-rs-spec users] [jsr339-experts] Re: Re: Re: FilterAction and FilterContext

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Thu, 01 Dec 2011 16:59:44 +0100

On 11/30/2011 02:20 PM, Bill Burke wrote:
>
>
> On 11/30/11 5:52 AM, Marek Potociar wrote:
>>
>> public interface NextAction { }
>>
>> IMO it should be defined as an inner interface of FilterContext. We can add some methods if we find it useful. Otherwise
>> it should be up to the implementation how to implement the interface and what methods should be internally provided.
>
> Yuck. -1 on a special interface. What about my proposal with filter returning void, and FilterContext having a state or
> a set of boolean methods that describe the state:
>
> void preFilter(FilterContext ctx) {
> context.stop();
> }
>

As I said, passing in a mutable context and returning void is a viable option IMO. context.stop(response) or
context.respondWith(response) or similar is definitely a better option than ambiguous context.setResponse(...).

If we are going to vote, this will be my second preference. I still find returning the next action superior though. Let
me try to summarize why (sorry for a longer prose):

Procedural style of mutable input/output context value(s) (as proposed above) work well with wrapping filters (e.g.
Servlet filters) without placing any significant restrictions on implementations, (e.g. internal threading model of the
filter). This simply works because of the nature of wrapping filters - their implementations have full control over how
the rest of the filter chain is invoked.

We are however dealing with non-wrapping filters here. These filters do not have the full control over the filter chain.
Unless we want to make certain limiting assumptions about what filters can or cannot do especially wrt. internal
threading model (which I would find unnecessary and very unfortunate), exploring the mutable context instance after the
filter has returned is a potentially unsafe operation.

For this and some other reasons, non-wrapping filters are naturally designed as functions that take immutable input
(context) and produce immutable output (continuation). The immutability is on the interface level, implementation
details may obviously vary based on the particular implementation requirements. This design is evolvable, does not place
unnecessary constraints on filter implementations and even allows for some runtime performance boosts due to
optimizations based on code inspection and analysis.

From the user perspective, returning a next action explicitly makes code more readable and less prone to accidental
hard-to chase bugs typical to mutable state objects. Additionally this "functional" programming style is promotes
stateless coding, which is arguably simpler to maintain as well as nicely aligned with the basic REST principles.

In fact, I am not aware of any serious framework that would expose non-wrapping filters as procedural ones. All
implementations I know about use functional immutable context-to-continuation API (to name a few - Grizzly, Ning HTTP
Client, Metro). Note e.g. that in Ning they use context as a continuation, but that's because their *whole* API is
immutable.

Howgh.

> ctx.isStopped();

That's not needed as part of the public interface, is it?

>
> BTW, We're starting to implement the spec next week. I'll probably have a lot more comments when we start playing with
> things.

Great, looking forward.

Marek