Hi,
Now that the container SPI is refactored we can move on to specifying
filters.
Any filter SPI cannot be stack based (like the Russian doll filter API
on Jersey client-side) because Jersey server-side needs to be in control
of the stack (e.g. writing out multiple responses for comet).
The disadvantage of a non-stack-based approach is it means state cannot
be as easily shared between inbound and outbound filtering. But how
common is that on the server side?
So i propose the following provider interfaces:
public interface ContainerRequestFilter {
ContainerRequest filter(ContainerRequest request);
}
public interface ContainerResponseFilter {
ContainerResponse filter(ContainerResponse response);
}
An implementation can throw a WebApplicationException to terminate the
filter chain prematurely with it's own response.
A provider implementation could consist of:
@Provider
public class MyFilter
implements ContainerRequestFilter, ContainerRequestFilter {
...
}
and thus only one instance would be created for both in-bound and
out-bound filtering, which means thread-local state could be shared.
The next question is how to order/prioritize filters.
I think the application should declare two lists of filter classes, for
inbound and outbound. This makes it easy to specify using ResourceConfig
or in the web.xml.
Here is an example of what a transport-based GZIP filter might look like:
@Provider
public class GZIPFilter
implements ContainerRequestFilter, ContainerRequestFilter {
ContainerRequest filter(ContainerRequest request) {
if (transport encoding is GZIP) {
request.setEntity(new GZIPInputStream(request.getEntity());
}
return request;
}
private static class GZIPWriter
implements ContainerResponseWriter {
ContainerResponseWriter crw;
GZIPWriter(ContainerResponseWriter crw) { this.crw = crw; }
OutputStream writeStatusAndHeaders(
long contentLength,
ContainerResponse response) throws IOException {
OutputStream o = crw.writeStatusAndHeaders(contentLength,
response);
return new GZIPOutputStream(o);
}
}
ContainerResponse filter(ContainerResponse response) {
if (transport encoding is GZIP) {
response.setContainerResponseWriter(
new GZIPWriter(response.getContainerResponseWriter()));
}
return response;
}
}
We need the above as well as logging, fake PUT/DELETE, URI-based conneg,
URI C14N with redirection filters.
This is a long shot but it may even be possible to reuse such filters
specifically targeted at resources.
Paul.
--
| ? + ? = To question
----------------\
Paul Sandoz
x38109
+33-4-76188109