users@jersey.java.net

Re: [Jersey] Resource filtering proposal

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 12 Jan 2009 17:06:51 +0100

On Jan 12, 2009, at 4:09 PM, Marc Hadley wrote:

> On Jan 12, 2009, at 6:56 AM, Paul Sandoz wrote:
>>> Resource filtering will reuse the ContainerRequestFilter and
>>> ContainerResponseFilter interfaces.
>>>
>>> There are two ways resource filters can be registered:
>>>
>>> 1) Via @ResourceFilters by declaring an array of classes that
>>> implement ResourceFilter.
>>> This annotation may occur on a resource class, resource method,
>>> sub-resource method or sub-resource locator.
>>>
>>> 2) Via a registered ResourceFilterFactory instance. A
>>> ResourceFilterFactory will be applied to the abstract model of
>>> a resource class, resource method, sub-resource method or sub-
>>> resource locator. This is a mechanism to provide
>>> general resource filters dependent on the specifics of a
>>> resource. A list of ResourceFilterFactory can be registered
>>> with the application.
>>>
> Will this use the standard @Provider mechanism in conjunction with
> the Application class ?

Yes. And ResourceFilter classes declared by the annotation would also
be instantiated as singletons.


>
>
>>> Filter processing will occur in the following order:
>>>
>>> - list of system-based ResourceFilter, in order, obtained from
>>> list of system ResourceFilterFactory
>>>
>>> - list of ResourceFilter, in order, obtained from list of
>>> ResourceFilterFactory.
>>>
>>> - array of ResourceFilter, in order, declared by @ResourceFilters.
>>>
> Is the order the same for request and response processing or does it
> depend on client vs server side, request vs response. Sometimes
> you'd like the first filter processed for a request to be the last
> filter processed for a response, e.g. a filter that supports some
> form of encoding should get first crack at a request otherwise the
> remaining filters might not understand the request format, similarly
> you'd want the same filter to run last if it also applies an
> encoding for the same reason.

I was assuming it would be in the order as you state.

The current filter support defines two separate lists where classes or
instances of ContainerRequestFilter and ContainerReponseFilter to be
declared. Both are processed from first entry to last entry, so it is
possible to support either way.


>
>
>>> Issues:
>>>
>>> - It is not intended that response filters will be processed if an
>>> exception is thrown before the response filters are to be
>>> processed, for
>>> example by client filters or by the application. Part of the
>>> reason is that there may not be any response information to be
>>> processed.
>>> Exceptions are mapped to responses way up the call stack in the
>>> WebApplication and thus requiring no logic in the call stack to
>>> handle error conditions.
>>>
>>
>> It should be possible to trap such exceptions and map them to
>> Response closer to the source. Need to be careful about exceptions
>> thrown in request and response filters.
>>
>> Other issues/points:
>>
>> - The support for @ResourceFilters can be implemented by a
>> ResourceFilterFactory.
>>
>> - On sub-resource locators: the response filters will be applied
>> after the resource method has returned and not after the sub-resource
>> locator returns (since a response will not be produced unless an
>> exception is thrown). Not sure if this is a good idea. Perhaps only
>> request filter should be supported? Asynchronous responses (e.g.
>> supported via Atmosphere) will go through a different thread.
>>
> What will happen if a subresource locator and the method on returned
> subresource both declare the same filter, will the filter be run
> twice ?
>

Yes.


>> - On resource classes. Request filtering on root resource classes
>> for per-request life-cycle can occur before construction, but this
>> cannot occur for classes/instances returned by sub-resource
>> locators. So there is an inconsistency.
>
> If the request filter is applied before the sub-resource locator
> method is invoked and the response filter then it would seem
> consistent.


To be consistent we would have to apply the class-level request
filters after construction of the class so that any resource returned
by a sub-resource locator could be filtered by class as well.


>> Does it make sense to support
>> the following instead?: Filters declared on a classes will applied
>> pre-post method invocation, Filters declared on a method override
>> that declared (if any) on the class?
>>
> Overriding would be consistent with the way other annotations work.
>

Yes. So it comes down to a design choice of filter layering (class
then method) or filter inheritance.

Paul.

> Marc.
>
>>>
>>> /**
>>> * A resource filter factory responsible for creating {_at_link
>>> ResourceFilter}
>>> * instances that match elements of the abstract resource model.
>>> *
>>> * @author Paul.Sandoz_at_Sun.Com
>>> */
>>> public interface ResourceFilterFactory {
>>> /**
>>> * Create a {_at_link ResourceFilter} instance given an element
>>> * of the abstract resource model.
>>> *
>>> * @param aae the abstract annotated element. This may be an
>>> instance
>>> * of the following: {_at_link AbstractResource}, {_at_link
>>> AbstractResourceMethod},
>>> * {_at_link AbstractSubResourceMethod} or {_at_link
>>> AbstractSubResourceLocator}.
>>> * @return the resource filter, otherwise null if no resource
>>> filter is
>>> * associated with the annotated element.
>>> */
>>> ResourceFilter create(AbstractAnnotatedElement aae);
>>> }
>>>
>>>
>>> /**
>>> * A resource filter to be used to filter a resource class, a
>>> resource method,
>>> * a sub-resource method, or a sub-resource locator.
>>> *
>>> * @author Paul.Sandoz_at_Sun.Com
>>> */
>>> public interface ResourceFilter {
>>>
>>> /**
>>> * Get the request filter.
>>> *
>>> * @return the request filter, otherwise null if request filtering
>>> * is not supported.
>>> */
>>> ContainerRequestFilter getRequestFilter();
>>>
>>> /**
>>> * Get the response filter.
>>> *
>>> * @return the response filter, otherwise null if response
>>> filtering
>>> * is not supported.
>>> */
>>> ContainerResponseFilter getResponseFilter();
>>> }
>>>
>>> /**
>>> * Defines the list of application-declared {_at_link ResourceFilter}
>>> * associated with a a resource class, a resource method,
>>> * a sub-resource method, or a sub-resource locator.
>>> *
>>> * @author Paul.Sandoz_at_Sun.Com
>>> */
>>> @Target({ElementType.TYPE, ElementType.METHOD})
>>> @Retention(RetentionPolicy.RUNTIME)
>>> public @interface ResourceFilters {
>>> Class<ResourceFilter>[] value();
>>> }
>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>
> ---
> Marc Hadley <marc.hadley at sun.com>
> CTO Office, Sun Microsystems.
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>